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 |