| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/password_manager/native_backend_kwallet_x.h" | 5 #include "chrome/browser/password_manager/native_backend_kwallet_x.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 a.signon_realm == b.signon_realm && | 60 a.signon_realm == b.signon_realm && |
| 61 a.username_element == b.username_element && | 61 a.username_element == b.username_element && |
| 62 a.username_value == b.username_value; | 62 a.username_value == b.username_value; |
| 63 } | 63 } |
| 64 | 64 |
| 65 // Checks a serialized list of PasswordForms for sanity. Returns true if OK. | 65 // Checks a serialized list of PasswordForms for sanity. Returns true if OK. |
| 66 // Note that |realm| is only used for generating a useful warning message. | 66 // Note that |realm| is only used for generating a useful warning message. |
| 67 bool CheckSerializedValue(const uint8_t* byte_array, | 67 bool CheckSerializedValue(const uint8_t* byte_array, |
| 68 size_t length, | 68 size_t length, |
| 69 const std::string& realm) { | 69 const std::string& realm) { |
| 70 const Pickle::Header* header = | 70 const base::Pickle::Header* header = |
| 71 reinterpret_cast<const Pickle::Header*>(byte_array); | 71 reinterpret_cast<const base::Pickle::Header*>(byte_array); |
| 72 if (length < sizeof(*header) || | 72 if (length < sizeof(*header) || |
| 73 header->payload_size > length - sizeof(*header)) { | 73 header->payload_size > length - sizeof(*header)) { |
| 74 LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")"; | 74 LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")"; |
| 75 return false; | 75 return false; |
| 76 } | 76 } |
| 77 return true; | 77 return true; |
| 78 } | 78 } |
| 79 | 79 |
| 80 // Convenience function to read a GURL from a Pickle. Assumes the URL has | 80 // Convenience function to read a GURL from a Pickle. Assumes the URL has |
| 81 // been written as a UTF-8 string. Returns true on success. | 81 // been written as a UTF-8 string. Returns true on success. |
| 82 bool ReadGURL(PickleIterator* iter, bool warn_only, GURL* url) { | 82 bool ReadGURL(base::PickleIterator* iter, bool warn_only, GURL* url) { |
| 83 std::string url_string; | 83 std::string url_string; |
| 84 if (!iter->ReadString(&url_string)) { | 84 if (!iter->ReadString(&url_string)) { |
| 85 if (!warn_only) | 85 if (!warn_only) |
| 86 LOG(ERROR) << "Failed to deserialize URL."; | 86 LOG(ERROR) << "Failed to deserialize URL."; |
| 87 *url = GURL(); | 87 *url = GURL(); |
| 88 return false; | 88 return false; |
| 89 } | 89 } |
| 90 *url = GURL(url_string); | 90 *url = GURL(url_string); |
| 91 return true; | 91 return true; |
| 92 } | 92 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 106 } | 106 } |
| 107 | 107 |
| 108 // Deserializes a list of credentials from the wallet to |forms| (replacing | 108 // Deserializes a list of credentials from the wallet to |forms| (replacing |
| 109 // the contents of |forms|). |size_32| controls reading the size field within | 109 // the contents of |forms|). |size_32| controls reading the size field within |
| 110 // the pickle as 32 bits. We used to use Pickle::WriteSize() to write the number | 110 // the pickle as 32 bits. We used to use Pickle::WriteSize() to write the number |
| 111 // of password forms, but that has a different size on 32- and 64-bit systems. | 111 // of password forms, but that has a different size on 32- and 64-bit systems. |
| 112 // So, now we always write a 64-bit quantity, but we support trying to read it | 112 // So, now we always write a 64-bit quantity, but we support trying to read it |
| 113 // as either size when reading old pickles that fail to deserialize using the | 113 // as either size when reading old pickles that fail to deserialize using the |
| 114 // native size. Returns true on success. | 114 // native size. Returns true on success. |
| 115 bool DeserializeValueSize(const std::string& signon_realm, | 115 bool DeserializeValueSize(const std::string& signon_realm, |
| 116 const PickleIterator& init_iter, | 116 const base::PickleIterator& init_iter, |
| 117 int version, | 117 int version, |
| 118 bool size_32, | 118 bool size_32, |
| 119 bool warn_only, | 119 bool warn_only, |
| 120 ScopedVector<autofill::PasswordForm>* forms) { | 120 ScopedVector<autofill::PasswordForm>* forms) { |
| 121 PickleIterator iter = init_iter; | 121 base::PickleIterator iter = init_iter; |
| 122 | 122 |
| 123 size_t count = 0; | 123 size_t count = 0; |
| 124 if (size_32) { | 124 if (size_32) { |
| 125 uint32_t count_32 = 0; | 125 uint32_t count_32 = 0; |
| 126 if (!iter.ReadUInt32(&count_32)) { | 126 if (!iter.ReadUInt32(&count_32)) { |
| 127 LOG(ERROR) << "Failed to deserialize KWallet entry " | 127 LOG(ERROR) << "Failed to deserialize KWallet entry " |
| 128 << "(realm: " << signon_realm << ")"; | 128 << "(realm: " << signon_realm << ")"; |
| 129 return false; | 129 return false; |
| 130 } | 130 } |
| 131 count = count_32; | 131 count = count_32; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 | 228 |
| 229 converted_forms.push_back(form.Pass()); | 229 converted_forms.push_back(form.Pass()); |
| 230 } | 230 } |
| 231 | 231 |
| 232 forms->swap(converted_forms); | 232 forms->swap(converted_forms); |
| 233 return true; | 233 return true; |
| 234 } | 234 } |
| 235 | 235 |
| 236 // Serializes a list of PasswordForms to be stored in the wallet. | 236 // Serializes a list of PasswordForms to be stored in the wallet. |
| 237 void SerializeValue(const std::vector<autofill::PasswordForm*>& forms, | 237 void SerializeValue(const std::vector<autofill::PasswordForm*>& forms, |
| 238 Pickle* pickle) { | 238 base::Pickle* pickle) { |
| 239 pickle->WriteInt(kPickleVersion); | 239 pickle->WriteInt(kPickleVersion); |
| 240 pickle->WriteSizeT(forms.size()); | 240 pickle->WriteSizeT(forms.size()); |
| 241 for (autofill::PasswordForm* form : forms) { | 241 for (autofill::PasswordForm* form : forms) { |
| 242 pickle->WriteInt(form->scheme); | 242 pickle->WriteInt(form->scheme); |
| 243 pickle->WriteString(form->origin.spec()); | 243 pickle->WriteString(form->origin.spec()); |
| 244 pickle->WriteString(form->action.spec()); | 244 pickle->WriteString(form->action.spec()); |
| 245 pickle->WriteString16(form->username_element); | 245 pickle->WriteString16(form->username_element); |
| 246 pickle->WriteString16(form->username_value); | 246 pickle->WriteString16(form->username_value); |
| 247 pickle->WriteString16(form->password_element); | 247 pickle->WriteString16(form->password_element); |
| 248 pickle->WriteString16(form->password_value); | 248 pickle->WriteString16(form->password_value); |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 return false; | 630 return false; |
| 631 if (!CheckSerializedValue(bytes, length, signon_realm)) { | 631 if (!CheckSerializedValue(bytes, length, signon_realm)) { |
| 632 // This is weird, but we choose not to call it an error. There is an | 632 // This is weird, but we choose not to call it an error. There is an |
| 633 // invalid entry somehow, but by just ignoring it, we make it easier to | 633 // invalid entry somehow, but by just ignoring it, we make it easier to |
| 634 // repair without having to delete it using kwalletmanager (that is, by | 634 // repair without having to delete it using kwalletmanager (that is, by |
| 635 // just saving a new password within this realm to overwrite it). | 635 // just saving a new password within this realm to overwrite it). |
| 636 return true; | 636 return true; |
| 637 } | 637 } |
| 638 | 638 |
| 639 // Can't we all just agree on whether bytes are signed or not? Please? | 639 // Can't we all just agree on whether bytes are signed or not? Please? |
| 640 Pickle pickle(reinterpret_cast<const char*>(bytes), length); | 640 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 641 *forms = DeserializeValue(signon_realm, pickle); | 641 *forms = DeserializeValue(signon_realm, pickle); |
| 642 } | 642 } |
| 643 | 643 |
| 644 return true; | 644 return true; |
| 645 } | 645 } |
| 646 | 646 |
| 647 bool NativeBackendKWallet::GetLoginsList( | 647 bool NativeBackendKWallet::GetLoginsList( |
| 648 BlacklistOptions options, | 648 BlacklistOptions options, |
| 649 int wallet_handle, | 649 int wallet_handle, |
| 650 ScopedVector<autofill::PasswordForm>* forms) { | 650 ScopedVector<autofill::PasswordForm>* forms) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 size_t length = 0; | 712 size_t length = 0; |
| 713 if (!reader.PopArrayOfBytes(&bytes, &length)) { | 713 if (!reader.PopArrayOfBytes(&bytes, &length)) { |
| 714 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " | 714 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " |
| 715 << response->ToString(); | 715 << response->ToString(); |
| 716 return false; | 716 return false; |
| 717 } | 717 } |
| 718 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) | 718 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) |
| 719 continue; | 719 continue; |
| 720 | 720 |
| 721 // Can't we all just agree on whether bytes are signed or not? Please? | 721 // Can't we all just agree on whether bytes are signed or not? Please? |
| 722 Pickle pickle(reinterpret_cast<const char*>(bytes), length); | 722 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 723 AppendSecondToFirst(forms, DeserializeValue(signon_realm, pickle)); | 723 AppendSecondToFirst(forms, DeserializeValue(signon_realm, pickle)); |
| 724 } | 724 } |
| 725 return true; | 725 return true; |
| 726 } | 726 } |
| 727 | 727 |
| 728 bool NativeBackendKWallet::SetLoginsList( | 728 bool NativeBackendKWallet::SetLoginsList( |
| 729 const std::vector<autofill::PasswordForm*>& forms, | 729 const std::vector<autofill::PasswordForm*>& forms, |
| 730 const std::string& signon_realm, | 730 const std::string& signon_realm, |
| 731 int wallet_handle) { | 731 int wallet_handle) { |
| 732 if (forms.empty()) { | 732 if (forms.empty()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 749 if (!reader.PopInt32(&ret)) { | 749 if (!reader.PopInt32(&ret)) { |
| 750 LOG(ERROR) << "Error reading response from kwalletd (removeEntry): " | 750 LOG(ERROR) << "Error reading response from kwalletd (removeEntry): " |
| 751 << response->ToString(); | 751 << response->ToString(); |
| 752 return false; | 752 return false; |
| 753 } | 753 } |
| 754 if (ret != 0) | 754 if (ret != 0) |
| 755 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; | 755 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; |
| 756 return ret == 0; | 756 return ret == 0; |
| 757 } | 757 } |
| 758 | 758 |
| 759 Pickle value; | 759 base::Pickle value; |
| 760 SerializeValue(forms, &value); | 760 SerializeValue(forms, &value); |
| 761 | 761 |
| 762 dbus::MethodCall method_call(kKWalletInterface, "writeEntry"); | 762 dbus::MethodCall method_call(kKWalletInterface, "writeEntry"); |
| 763 dbus::MessageWriter builder(&method_call); | 763 dbus::MessageWriter builder(&method_call); |
| 764 builder.AppendInt32(wallet_handle); // handle | 764 builder.AppendInt32(wallet_handle); // handle |
| 765 builder.AppendString(folder_name_); // folder | 765 builder.AppendString(folder_name_); // folder |
| 766 builder.AppendString(signon_realm); // key | 766 builder.AppendString(signon_realm); // key |
| 767 builder.AppendArrayOfBytes(static_cast<const uint8_t*>(value.data()), | 767 builder.AppendArrayOfBytes(static_cast<const uint8_t*>(value.data()), |
| 768 value.size()); // value | 768 value.size()); // value |
| 769 builder.AppendString(app_name_); // appid | 769 builder.AppendString(app_name_); // appid |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 size_t length = 0; | 849 size_t length = 0; |
| 850 if (!reader.PopArrayOfBytes(&bytes, &length)) { | 850 if (!reader.PopArrayOfBytes(&bytes, &length)) { |
| 851 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " | 851 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " |
| 852 << response->ToString(); | 852 << response->ToString(); |
| 853 continue; | 853 continue; |
| 854 } | 854 } |
| 855 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) | 855 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) |
| 856 continue; | 856 continue; |
| 857 | 857 |
| 858 // Can't we all just agree on whether bytes are signed or not? Please? | 858 // Can't we all just agree on whether bytes are signed or not? Please? |
| 859 Pickle pickle(reinterpret_cast<const char*>(bytes), length); | 859 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 860 ScopedVector<autofill::PasswordForm> all_forms = | 860 ScopedVector<autofill::PasswordForm> all_forms = |
| 861 DeserializeValue(signon_realm, pickle); | 861 DeserializeValue(signon_realm, pickle); |
| 862 | 862 |
| 863 ScopedVector<autofill::PasswordForm> kept_forms; | 863 ScopedVector<autofill::PasswordForm> kept_forms; |
| 864 kept_forms.reserve(all_forms.size()); | 864 kept_forms.reserve(all_forms.size()); |
| 865 base::Time autofill::PasswordForm::*date_member = | 865 base::Time autofill::PasswordForm::*date_member = |
| 866 date_to_compare == CREATION_TIMESTAMP | 866 date_to_compare == CREATION_TIMESTAMP |
| 867 ? &autofill::PasswordForm::date_created | 867 ? &autofill::PasswordForm::date_created |
| 868 : &autofill::PasswordForm::date_synced; | 868 : &autofill::PasswordForm::date_synced; |
| 869 for (auto& saved_form : all_forms) { | 869 for (auto& saved_form : all_forms) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 881 ok = false; | 881 ok = false; |
| 882 changes->clear(); | 882 changes->clear(); |
| 883 } | 883 } |
| 884 } | 884 } |
| 885 return ok; | 885 return ok; |
| 886 } | 886 } |
| 887 | 887 |
| 888 // static | 888 // static |
| 889 ScopedVector<autofill::PasswordForm> NativeBackendKWallet::DeserializeValue( | 889 ScopedVector<autofill::PasswordForm> NativeBackendKWallet::DeserializeValue( |
| 890 const std::string& signon_realm, | 890 const std::string& signon_realm, |
| 891 const Pickle& pickle) { | 891 const base::Pickle& pickle) { |
| 892 PickleIterator iter(pickle); | 892 base::PickleIterator iter(pickle); |
| 893 | 893 |
| 894 int version = -1; | 894 int version = -1; |
| 895 if (!iter.ReadInt(&version) || | 895 if (!iter.ReadInt(&version) || |
| 896 version < 0 || version > kPickleVersion) { | 896 version < 0 || version > kPickleVersion) { |
| 897 LOG(ERROR) << "Failed to deserialize KWallet entry " | 897 LOG(ERROR) << "Failed to deserialize KWallet entry " |
| 898 << "(realm: " << signon_realm << ")"; | 898 << "(realm: " << signon_realm << ")"; |
| 899 return ScopedVector<autofill::PasswordForm>(); | 899 return ScopedVector<autofill::PasswordForm>(); |
| 900 } | 900 } |
| 901 | 901 |
| 902 ScopedVector<autofill::PasswordForm> forms; | 902 ScopedVector<autofill::PasswordForm> forms; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 } | 1005 } |
| 1006 | 1006 |
| 1007 return handle; | 1007 return handle; |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { | 1010 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { |
| 1011 // Originally, the folder name was always just "Chrome Form Data". | 1011 // Originally, the folder name was always just "Chrome Form Data". |
| 1012 // Now we use it to distinguish passwords for different profiles. | 1012 // Now we use it to distinguish passwords for different profiles. |
| 1013 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_); | 1013 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_); |
| 1014 } | 1014 } |
| OLD | NEW |