| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 #include "sql/statement.h" | 35 #include "sql/statement.h" |
| 36 #include "sql/transaction.h" | 36 #include "sql/transaction.h" |
| 37 #include "url/origin.h" | 37 #include "url/origin.h" |
| 38 #include "url/url_constants.h" | 38 #include "url/url_constants.h" |
| 39 | 39 |
| 40 using autofill::PasswordForm; | 40 using autofill::PasswordForm; |
| 41 | 41 |
| 42 namespace password_manager { | 42 namespace password_manager { |
| 43 | 43 |
| 44 // The current version number of the login database schema. | 44 // The current version number of the login database schema. |
| 45 const int kCurrentVersionNumber = 17; | 45 const int kCurrentVersionNumber = 18; |
| 46 // The oldest version of the schema such that a legacy Chrome client using that | 46 // The oldest version of the schema such that a legacy Chrome client using that |
| 47 // version can still read/write the current database. | 47 // version can still read/write the current database. |
| 48 const int kCompatibleVersionNumber = 14; | 48 const int kCompatibleVersionNumber = 18; |
| 49 | 49 |
| 50 base::Pickle SerializeVector(const std::vector<base::string16>& vec) { | 50 base::Pickle SerializeVector(const std::vector<base::string16>& vec) { |
| 51 base::Pickle p; | 51 base::Pickle p; |
| 52 for (size_t i = 0; i < vec.size(); ++i) { | 52 for (size_t i = 0; i < vec.size(); ++i) { |
| 53 p.WriteString16(vec[i]); | 53 p.WriteString16(vec[i]); |
| 54 } | 54 } |
| 55 return p; | 55 return p; |
| 56 } | 56 } |
| 57 | 57 |
| 58 std::vector<base::string16> DeserializeVector(const base::Pickle& p) { | 58 std::vector<base::string16> DeserializeVector(const base::Pickle& p) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 71 // Convenience enum for interacting with SQL queries that use all the columns. | 71 // Convenience enum for interacting with SQL queries that use all the columns. |
| 72 enum LoginTableColumns { | 72 enum LoginTableColumns { |
| 73 COLUMN_ORIGIN_URL = 0, | 73 COLUMN_ORIGIN_URL = 0, |
| 74 COLUMN_ACTION_URL, | 74 COLUMN_ACTION_URL, |
| 75 COLUMN_USERNAME_ELEMENT, | 75 COLUMN_USERNAME_ELEMENT, |
| 76 COLUMN_USERNAME_VALUE, | 76 COLUMN_USERNAME_VALUE, |
| 77 COLUMN_PASSWORD_ELEMENT, | 77 COLUMN_PASSWORD_ELEMENT, |
| 78 COLUMN_PASSWORD_VALUE, | 78 COLUMN_PASSWORD_VALUE, |
| 79 COLUMN_SUBMIT_ELEMENT, | 79 COLUMN_SUBMIT_ELEMENT, |
| 80 COLUMN_SIGNON_REALM, | 80 COLUMN_SIGNON_REALM, |
| 81 COLUMN_SSL_VALID, | |
| 82 COLUMN_PREFERRED, | 81 COLUMN_PREFERRED, |
| 83 COLUMN_DATE_CREATED, | 82 COLUMN_DATE_CREATED, |
| 84 COLUMN_BLACKLISTED_BY_USER, | 83 COLUMN_BLACKLISTED_BY_USER, |
| 85 COLUMN_SCHEME, | 84 COLUMN_SCHEME, |
| 86 COLUMN_PASSWORD_TYPE, | 85 COLUMN_PASSWORD_TYPE, |
| 87 COLUMN_POSSIBLE_USERNAMES, | 86 COLUMN_POSSIBLE_USERNAMES, |
| 88 COLUMN_TIMES_USED, | 87 COLUMN_TIMES_USED, |
| 89 COLUMN_FORM_DATA, | 88 COLUMN_FORM_DATA, |
| 90 COLUMN_DATE_SYNCED, | 89 COLUMN_DATE_SYNCED, |
| 91 COLUMN_DISPLAY_NAME, | 90 COLUMN_DISPLAY_NAME, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 118 sql::Statement* s) { | 117 sql::Statement* s) { |
| 119 s->BindString(COLUMN_ORIGIN_URL, form.origin.spec()); | 118 s->BindString(COLUMN_ORIGIN_URL, form.origin.spec()); |
| 120 s->BindString(COLUMN_ACTION_URL, form.action.spec()); | 119 s->BindString(COLUMN_ACTION_URL, form.action.spec()); |
| 121 s->BindString16(COLUMN_USERNAME_ELEMENT, form.username_element); | 120 s->BindString16(COLUMN_USERNAME_ELEMENT, form.username_element); |
| 122 s->BindString16(COLUMN_USERNAME_VALUE, form.username_value); | 121 s->BindString16(COLUMN_USERNAME_VALUE, form.username_value); |
| 123 s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); | 122 s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); |
| 124 s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), | 123 s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), |
| 125 static_cast<int>(encrypted_password.length())); | 124 static_cast<int>(encrypted_password.length())); |
| 126 s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); | 125 s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); |
| 127 s->BindString(COLUMN_SIGNON_REALM, form.signon_realm); | 126 s->BindString(COLUMN_SIGNON_REALM, form.signon_realm); |
| 128 s->BindInt(COLUMN_SSL_VALID, form.ssl_valid); | |
| 129 s->BindInt(COLUMN_PREFERRED, form.preferred); | 127 s->BindInt(COLUMN_PREFERRED, form.preferred); |
| 130 s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToInternalValue()); | 128 s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToInternalValue()); |
| 131 s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); | 129 s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); |
| 132 s->BindInt(COLUMN_SCHEME, form.scheme); | 130 s->BindInt(COLUMN_SCHEME, form.scheme); |
| 133 s->BindInt(COLUMN_PASSWORD_TYPE, form.type); | 131 s->BindInt(COLUMN_PASSWORD_TYPE, form.type); |
| 134 base::Pickle usernames_pickle = | 132 base::Pickle usernames_pickle = |
| 135 SerializeVector(form.other_possible_usernames); | 133 SerializeVector(form.other_possible_usernames); |
| 136 s->BindBlob(COLUMN_POSSIBLE_USERNAMES, | 134 s->BindBlob(COLUMN_POSSIBLE_USERNAMES, |
| 137 usernames_pickle.data(), | 135 usernames_pickle.data(), |
| 138 usernames_pickle.size()); | 136 usernames_pickle.size()); |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 DCHECK_EQ(14u, version); | 417 DCHECK_EQ(14u, version); |
| 420 | 418 |
| 421 // Version 15. | 419 // Version 15. |
| 422 builder->SealVersion(); | 420 builder->SealVersion(); |
| 423 // Version 16. | 421 // Version 16. |
| 424 builder->SealVersion(); | 422 builder->SealVersion(); |
| 425 // Version 17. | 423 // Version 17. |
| 426 version = builder->SealVersion(); | 424 version = builder->SealVersion(); |
| 427 DCHECK_EQ(17u, version); | 425 DCHECK_EQ(17u, version); |
| 428 | 426 |
| 427 // Version 18. |
| 428 builder->DropColumn("ssl_valid"); |
| 429 version = builder->SealVersion(); |
| 430 DCHECK_EQ(18u, version); |
| 431 |
| 429 DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builder->NumberOfColumns()) | 432 DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builder->NumberOfColumns()) |
| 430 << "Adjust LoginTableColumns if you change column definitions here."; | 433 << "Adjust LoginTableColumns if you change column definitions here."; |
| 431 } | 434 } |
| 432 | 435 |
| 433 // Call this after having called InitializeBuilder, to migrate the database from | 436 // Call this after having called InitializeBuilder, to migrate the database from |
| 434 // the current version to kCurrentVersionNumber. | 437 // the current version to kCurrentVersionNumber. |
| 435 bool MigrateLogins(unsigned current_version, | 438 bool MigrateLogins(unsigned current_version, |
| 436 SQLTableBuilder* builder, | 439 SQLTableBuilder* builder, |
| 437 sql::Connection* db) { | 440 sql::Connection* db) { |
| 438 if (!builder->MigrateFrom(current_version, db)) | 441 if (!builder->MigrateFrom(current_version, db)) |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 "WHERE b.blacklisted_by_user=0 AND b.username_value!='' " | 724 "WHERE b.blacklisted_by_user=0 AND b.username_value!='' " |
| 722 "AND a.signon_realm = b.signon_realm)")); | 725 "AND a.signon_realm = b.signon_realm)")); |
| 723 if (standalone_empty_usernames_statement.Step()) { | 726 if (standalone_empty_usernames_statement.Step()) { |
| 724 int num_entries = standalone_empty_usernames_statement.ColumnInt(0); | 727 int num_entries = standalone_empty_usernames_statement.ColumnInt(0); |
| 725 UMA_HISTOGRAM_COUNTS_100( | 728 UMA_HISTOGRAM_COUNTS_100( |
| 726 "PasswordManager.EmptyUsernames.WithoutCorrespondingNonempty", | 729 "PasswordManager.EmptyUsernames.WithoutCorrespondingNonempty", |
| 727 num_entries); | 730 num_entries); |
| 728 } | 731 } |
| 729 | 732 |
| 730 sql::Statement logins_with_schemes_statement(db_.GetUniqueStatement( | 733 sql::Statement logins_with_schemes_statement(db_.GetUniqueStatement( |
| 731 "SELECT signon_realm, origin_url, ssl_valid, blacklisted_by_user " | 734 "SELECT signon_realm, origin_url, blacklisted_by_user FROM logins;")); |
| 732 "FROM logins;")); | |
| 733 | 735 |
| 734 if (!logins_with_schemes_statement.is_valid()) | 736 if (!logins_with_schemes_statement.is_valid()) |
| 735 return; | 737 return; |
| 736 | 738 |
| 737 int android_logins = 0; | 739 int android_logins = 0; |
| 738 int ftp_logins = 0; | 740 int ftp_logins = 0; |
| 739 int http_logins = 0; | 741 int http_logins = 0; |
| 740 int https_logins = 0; | 742 int https_logins = 0; |
| 741 int other_logins = 0; | 743 int other_logins = 0; |
| 742 | 744 |
| 743 while (logins_with_schemes_statement.Step()) { | 745 while (logins_with_schemes_statement.Step()) { |
| 744 std::string signon_realm = logins_with_schemes_statement.ColumnString(0); | 746 std::string signon_realm = logins_with_schemes_statement.ColumnString(0); |
| 745 GURL origin_url = GURL(logins_with_schemes_statement.ColumnString(1)); | 747 GURL origin_url = GURL(logins_with_schemes_statement.ColumnString(1)); |
| 746 bool ssl_valid = !!logins_with_schemes_statement.ColumnInt(2); | 748 bool blacklisted_by_user = !!logins_with_schemes_statement.ColumnInt(2); |
| 747 bool blacklisted_by_user = !!logins_with_schemes_statement.ColumnInt(3); | |
| 748 if (blacklisted_by_user) | 749 if (blacklisted_by_user) |
| 749 continue; | 750 continue; |
| 750 | 751 |
| 751 if (IsValidAndroidFacetURI(signon_realm)) { | 752 if (IsValidAndroidFacetURI(signon_realm)) { |
| 752 ++android_logins; | 753 ++android_logins; |
| 753 } else if (origin_url.SchemeIs(url::kHttpsScheme)) { | 754 } else if (origin_url.SchemeIs(url::kHttpsScheme)) { |
| 754 ++https_logins; | 755 ++https_logins; |
| 755 metrics_util::LogUMAHistogramBoolean( | |
| 756 "PasswordManager.UserStoredPasswordWithInvalidSSLCert", !ssl_valid); | |
| 757 } else if (origin_url.SchemeIs(url::kHttpScheme)) { | 756 } else if (origin_url.SchemeIs(url::kHttpScheme)) { |
| 758 ++http_logins; | 757 ++http_logins; |
| 759 } else if (origin_url.SchemeIs(url::kFtpScheme)) { | 758 } else if (origin_url.SchemeIs(url::kFtpScheme)) { |
| 760 ++ftp_logins; | 759 ++ftp_logins; |
| 761 } else { | 760 } else { |
| 762 ++other_logins; | 761 ++other_logins; |
| 763 } | 762 } |
| 764 } | 763 } |
| 765 | 764 |
| 766 LogNumberOfAccountsForScheme("Android", android_logins); | 765 LogNumberOfAccountsForScheme("Android", android_logins); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 #endif | 834 #endif |
| 836 // Replacement is necessary to deal with updating imported credentials. See | 835 // Replacement is necessary to deal with updating imported credentials. See |
| 837 // crbug.com/349138 for details. | 836 // crbug.com/349138 for details. |
| 838 DCHECK(!update_statement_.empty()); | 837 DCHECK(!update_statement_.empty()); |
| 839 sql::Statement s( | 838 sql::Statement s( |
| 840 db_.GetCachedStatement(SQL_FROM_HERE, update_statement_.c_str())); | 839 db_.GetCachedStatement(SQL_FROM_HERE, update_statement_.c_str())); |
| 841 s.BindString(0, form.action.spec()); | 840 s.BindString(0, form.action.spec()); |
| 842 s.BindBlob(1, encrypted_password.data(), | 841 s.BindBlob(1, encrypted_password.data(), |
| 843 static_cast<int>(encrypted_password.length())); | 842 static_cast<int>(encrypted_password.length())); |
| 844 s.BindString16(2, form.submit_element); | 843 s.BindString16(2, form.submit_element); |
| 845 s.BindInt(3, form.ssl_valid); | 844 s.BindInt(3, form.preferred); |
| 846 s.BindInt(4, form.preferred); | 845 s.BindInt64(4, form.date_created.ToInternalValue()); |
| 847 s.BindInt64(5, form.date_created.ToInternalValue()); | 846 s.BindInt(5, form.blacklisted_by_user); |
| 848 s.BindInt(6, form.blacklisted_by_user); | 847 s.BindInt(6, form.scheme); |
| 849 s.BindInt(7, form.scheme); | 848 s.BindInt(7, form.type); |
| 850 s.BindInt(8, form.type); | |
| 851 base::Pickle pickle = SerializeVector(form.other_possible_usernames); | 849 base::Pickle pickle = SerializeVector(form.other_possible_usernames); |
| 852 s.BindBlob(9, pickle.data(), pickle.size()); | 850 s.BindBlob(8, pickle.data(), pickle.size()); |
| 853 s.BindInt(10, form.times_used); | 851 s.BindInt(9, form.times_used); |
| 854 base::Pickle form_data_pickle; | 852 base::Pickle form_data_pickle; |
| 855 autofill::SerializeFormData(form.form_data, &form_data_pickle); | 853 autofill::SerializeFormData(form.form_data, &form_data_pickle); |
| 856 s.BindBlob(11, form_data_pickle.data(), form_data_pickle.size()); | 854 s.BindBlob(10, form_data_pickle.data(), form_data_pickle.size()); |
| 857 s.BindInt64(12, form.date_synced.ToInternalValue()); | 855 s.BindInt64(11, form.date_synced.ToInternalValue()); |
| 858 s.BindString16(13, form.display_name); | 856 s.BindString16(12, form.display_name); |
| 859 s.BindString(14, form.icon_url.spec()); | 857 s.BindString(13, form.icon_url.spec()); |
| 860 // An empty Origin serializes as "null" which would be strange to store here. | 858 // An empty Origin serializes as "null" which would be strange to store here. |
| 861 s.BindString(15, form.federation_origin.unique() | 859 s.BindString(14, form.federation_origin.unique() |
| 862 ? std::string() | 860 ? std::string() |
| 863 : form.federation_origin.Serialize()); | 861 : form.federation_origin.Serialize()); |
| 864 s.BindInt(16, form.skip_zero_click); | 862 s.BindInt(15, form.skip_zero_click); |
| 865 s.BindInt(17, form.generation_upload_status); | 863 s.BindInt(16, form.generation_upload_status); |
| 866 | 864 |
| 867 // WHERE starts here. | 865 // WHERE starts here. |
| 868 s.BindString(18, form.origin.spec()); | 866 s.BindString(17, form.origin.spec()); |
| 869 s.BindString16(19, form.username_element); | 867 s.BindString16(18, form.username_element); |
| 870 s.BindString16(20, form.username_value); | 868 s.BindString16(19, form.username_value); |
| 871 s.BindString16(21, form.password_element); | 869 s.BindString16(20, form.password_element); |
| 872 s.BindString(22, form.signon_realm); | 870 s.BindString(21, form.signon_realm); |
| 873 | 871 |
| 874 if (!s.Run()) | 872 if (!s.Run()) |
| 875 return PasswordStoreChangeList(); | 873 return PasswordStoreChangeList(); |
| 876 | 874 |
| 877 PasswordStoreChangeList list; | 875 PasswordStoreChangeList list; |
| 878 if (db_.GetLastChangeCount()) | 876 if (db_.GetLastChangeCount()) |
| 879 list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form)); | 877 list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form)); |
| 880 | 878 |
| 881 return list; | 879 return list; |
| 882 } | 880 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 form->origin = GURL(tmp); | 973 form->origin = GURL(tmp); |
| 976 tmp = s.ColumnString(COLUMN_ACTION_URL); | 974 tmp = s.ColumnString(COLUMN_ACTION_URL); |
| 977 form->action = GURL(tmp); | 975 form->action = GURL(tmp); |
| 978 form->username_element = s.ColumnString16(COLUMN_USERNAME_ELEMENT); | 976 form->username_element = s.ColumnString16(COLUMN_USERNAME_ELEMENT); |
| 979 form->username_value = s.ColumnString16(COLUMN_USERNAME_VALUE); | 977 form->username_value = s.ColumnString16(COLUMN_USERNAME_VALUE); |
| 980 form->password_element = s.ColumnString16(COLUMN_PASSWORD_ELEMENT); | 978 form->password_element = s.ColumnString16(COLUMN_PASSWORD_ELEMENT); |
| 981 form->password_value = decrypted_password; | 979 form->password_value = decrypted_password; |
| 982 form->submit_element = s.ColumnString16(COLUMN_SUBMIT_ELEMENT); | 980 form->submit_element = s.ColumnString16(COLUMN_SUBMIT_ELEMENT); |
| 983 tmp = s.ColumnString(COLUMN_SIGNON_REALM); | 981 tmp = s.ColumnString(COLUMN_SIGNON_REALM); |
| 984 form->signon_realm = tmp; | 982 form->signon_realm = tmp; |
| 985 form->ssl_valid = (s.ColumnInt(COLUMN_SSL_VALID) > 0); | |
| 986 form->preferred = (s.ColumnInt(COLUMN_PREFERRED) > 0); | 983 form->preferred = (s.ColumnInt(COLUMN_PREFERRED) > 0); |
| 987 form->date_created = | 984 form->date_created = |
| 988 base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_CREATED)); | 985 base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_CREATED)); |
| 989 form->blacklisted_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0); | 986 form->blacklisted_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0); |
| 990 int scheme_int = s.ColumnInt(COLUMN_SCHEME); | 987 int scheme_int = s.ColumnInt(COLUMN_SCHEME); |
| 991 DCHECK_LE(0, scheme_int); | 988 DCHECK_LE(0, scheme_int); |
| 992 DCHECK_GE(PasswordForm::SCHEME_LAST, scheme_int); | 989 DCHECK_GE(PasswordForm::SCHEME_LAST, scheme_int); |
| 993 form->scheme = static_cast<PasswordForm::Scheme>(scheme_int); | 990 form->scheme = static_cast<PasswordForm::Scheme>(scheme_int); |
| 994 int type_int = s.ColumnInt(COLUMN_PASSWORD_TYPE); | 991 int type_int = s.ColumnInt(COLUMN_PASSWORD_TYPE); |
| 995 DCHECK(type_int >= 0 && type_int <= PasswordForm::TYPE_LAST) << type_int; | 992 DCHECK(type_int >= 0 && type_int <= PasswordForm::TYPE_LAST) << type_int; |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 DCHECK(blacklisted_statement_.empty()); | 1281 DCHECK(blacklisted_statement_.empty()); |
| 1285 blacklisted_statement_ = | 1282 blacklisted_statement_ = |
| 1286 "SELECT " + all_column_names + | 1283 "SELECT " + all_column_names + |
| 1287 " FROM logins WHERE blacklisted_by_user == ? ORDER BY origin_url"; | 1284 " FROM logins WHERE blacklisted_by_user == ? ORDER BY origin_url"; |
| 1288 DCHECK(encrypted_statement_.empty()); | 1285 DCHECK(encrypted_statement_.empty()); |
| 1289 encrypted_statement_ = | 1286 encrypted_statement_ = |
| 1290 "SELECT password_value FROM logins WHERE " + all_unique_key_column_names; | 1287 "SELECT password_value FROM logins WHERE " + all_unique_key_column_names; |
| 1291 } | 1288 } |
| 1292 | 1289 |
| 1293 } // namespace password_manager | 1290 } // namespace password_manager |
| OLD | NEW |