OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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_libsecret.h" | 5 #include "chrome/browser/password_manager/native_backend_libsecret.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <libsecret/secret.h> | 10 #include <libsecret/secret.h> |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 bool NativeBackendLibsecret::Init() { | 173 bool NativeBackendLibsecret::Init() { |
174 return LibsecretLoader::EnsureLibsecretLoaded(); | 174 return LibsecretLoader::EnsureLibsecretLoaded(); |
175 } | 175 } |
176 | 176 |
177 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin( | 177 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin( |
178 const PasswordForm& form) { | 178 const PasswordForm& form) { |
179 // Based on LoginDatabase::AddLogin(), we search for an existing match based | 179 // Based on LoginDatabase::AddLogin(), we search for an existing match based |
180 // on origin_url, username_element, username_value, password_element and | 180 // on origin_url, username_element, username_value, password_element and |
181 // signon_realm first, remove that, and then add the new entry. | 181 // signon_realm first, remove that, and then add the new entry. |
182 password_manager::PasswordStoreChangeList changes; | 182 password_manager::PasswordStoreChangeList changes; |
183 ScopedVector<autofill::PasswordForm> forms; | 183 std::vector<std::unique_ptr<PasswordForm>> forms; |
184 if (!AddUpdateLoginSearch(form, &forms)) | 184 if (!AddUpdateLoginSearch(form, &forms)) |
185 return changes; | 185 return changes; |
186 | 186 |
187 if (forms.size() > 0) { | 187 if (forms.size() > 0) { |
188 password_manager::PasswordStoreChangeList temp_changes; | 188 password_manager::PasswordStoreChangeList temp_changes; |
189 if (forms.size() > 1) { | 189 if (forms.size() > 1) { |
190 LOG(WARNING) << "Adding login when there are " << forms.size() | 190 LOG(WARNING) << "Adding login when there are " << forms.size() |
191 << " matching logins already!"; | 191 << " matching logins already!"; |
192 } | 192 } |
193 for (const PasswordForm* old_form : forms) { | 193 for (const auto& old_form : forms) { |
194 if (!RemoveLogin(*old_form, &temp_changes)) | 194 if (!RemoveLogin(*old_form, &temp_changes)) |
195 return changes; | 195 return changes; |
196 } | 196 } |
197 changes.push_back(password_manager::PasswordStoreChange( | 197 changes.push_back(password_manager::PasswordStoreChange( |
198 password_manager::PasswordStoreChange::REMOVE, *forms[0])); | 198 password_manager::PasswordStoreChange::REMOVE, *forms[0])); |
199 } | 199 } |
200 if (RawAddLogin(form)) { | 200 if (RawAddLogin(form)) { |
201 changes.push_back(password_manager::PasswordStoreChange( | 201 changes.push_back(password_manager::PasswordStoreChange( |
202 password_manager::PasswordStoreChange::ADD, form)); | 202 password_manager::PasswordStoreChange::ADD, form)); |
203 } | 203 } |
204 return changes; | 204 return changes; |
205 } | 205 } |
206 | 206 |
207 bool NativeBackendLibsecret::UpdateLogin( | 207 bool NativeBackendLibsecret::UpdateLogin( |
208 const PasswordForm& form, | 208 const PasswordForm& form, |
209 password_manager::PasswordStoreChangeList* changes) { | 209 password_manager::PasswordStoreChangeList* changes) { |
210 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by | 210 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by |
211 // origin_url, username_element, username_value, password_element, and | 211 // origin_url, username_element, username_value, password_element, and |
212 // signon_realm. We then compare the result to the updated form. If they | 212 // signon_realm. We then compare the result to the updated form. If they |
213 // differ in any of the mutable fields, then we remove the original, and | 213 // differ in any of the mutable fields, then we remove the original, and |
214 // then add the new entry. We'd add the new one first, and then delete the | 214 // then add the new entry. We'd add the new one first, and then delete the |
215 // original, but then the delete might actually delete the newly-added entry! | 215 // original, but then the delete might actually delete the newly-added entry! |
216 DCHECK(changes); | 216 DCHECK(changes); |
217 ScopedVector<autofill::PasswordForm> forms; | 217 std::vector<std::unique_ptr<PasswordForm>> forms; |
218 if (!AddUpdateLoginSearch(form, &forms)) | 218 if (!AddUpdateLoginSearch(form, &forms)) |
219 return false; | 219 return false; |
220 if (forms.empty()) | 220 if (forms.empty()) |
221 return true; | 221 return true; |
222 if (forms.size() == 1 && *forms.front() == form) | 222 if (forms.size() == 1 && *forms.front() == form) |
223 return true; | 223 return true; |
224 | 224 |
225 password_manager::PasswordStoreChangeList temp_changes; | 225 password_manager::PasswordStoreChangeList temp_changes; |
226 for (const PasswordForm* keychain_form : forms) { | 226 for (const auto& keychain_form : forms) { |
227 // Remove all the obsolete forms. Note that RemoveLogin can remove any form | 227 // Remove all the obsolete forms. Note that RemoveLogin can remove any form |
228 // matching the unique key. Thus, it's important to call it the right number | 228 // matching the unique key. Thus, it's important to call it the right number |
229 // of times. | 229 // of times. |
230 if (!RemoveLogin(*keychain_form, &temp_changes)) | 230 if (!RemoveLogin(*keychain_form, &temp_changes)) |
231 return false; | 231 return false; |
232 } | 232 } |
233 | 233 |
234 if (RawAddLogin(form)) { | 234 if (RawAddLogin(form)) { |
235 password_manager::PasswordStoreChange change( | 235 password_manager::PasswordStoreChange change( |
236 password_manager::PasswordStoreChange::UPDATE, form); | 236 password_manager::PasswordStoreChange::UPDATE, form); |
237 changes->push_back(change); | 237 changes->push_back(change); |
238 return true; | 238 return true; |
239 } | 239 } |
240 return false; | 240 return false; |
241 } | 241 } |
242 | 242 |
243 bool NativeBackendLibsecret::RemoveLogin( | 243 bool NativeBackendLibsecret::RemoveLogin( |
244 const autofill::PasswordForm& form, | 244 const PasswordForm& form, |
245 password_manager::PasswordStoreChangeList* changes) { | 245 password_manager::PasswordStoreChangeList* changes) { |
246 DCHECK(changes); | 246 DCHECK(changes); |
247 GError* error = nullptr; | 247 GError* error = nullptr; |
248 if (LibsecretLoader::secret_password_clear_sync( | 248 if (LibsecretLoader::secret_password_clear_sync( |
249 &kLibsecretSchema, nullptr, &error, "origin_url", | 249 &kLibsecretSchema, nullptr, &error, "origin_url", |
250 form.origin.spec().c_str(), "username_element", | 250 form.origin.spec().c_str(), "username_element", |
251 UTF16ToUTF8(form.username_element).c_str(), "username_value", | 251 UTF16ToUTF8(form.username_element).c_str(), "username_value", |
252 UTF16ToUTF8(form.username_value).c_str(), "password_element", | 252 UTF16ToUTF8(form.username_value).c_str(), "password_element", |
253 UTF16ToUTF8(form.password_element).c_str(), "signon_realm", | 253 UTF16ToUTF8(form.password_element).c_str(), "signon_realm", |
254 form.signon_realm.c_str(), "application", app_string_.c_str(), | 254 form.signon_realm.c_str(), "application", app_string_.c_str(), |
(...skipping 21 matching lines...) Expand all Loading... |
276 bool NativeBackendLibsecret::RemoveLoginsSyncedBetween( | 276 bool NativeBackendLibsecret::RemoveLoginsSyncedBetween( |
277 base::Time delete_begin, | 277 base::Time delete_begin, |
278 base::Time delete_end, | 278 base::Time delete_end, |
279 password_manager::PasswordStoreChangeList* changes) { | 279 password_manager::PasswordStoreChangeList* changes) { |
280 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); | 280 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); |
281 } | 281 } |
282 | 282 |
283 bool NativeBackendLibsecret::DisableAutoSignInForOrigins( | 283 bool NativeBackendLibsecret::DisableAutoSignInForOrigins( |
284 const base::Callback<bool(const GURL&)>& origin_filter, | 284 const base::Callback<bool(const GURL&)>& origin_filter, |
285 password_manager::PasswordStoreChangeList* changes) { | 285 password_manager::PasswordStoreChangeList* changes) { |
286 ScopedVector<autofill::PasswordForm> all_forms; | 286 std::vector<std::unique_ptr<PasswordForm>> all_forms; |
287 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) | 287 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) |
288 return false; | 288 return false; |
289 | 289 |
290 for (auto* form : all_forms) { | 290 for (const std::unique_ptr<PasswordForm>& form : all_forms) { |
291 if (origin_filter.Run(form->origin) && !form->skip_zero_click) { | 291 if (origin_filter.Run(form->origin) && !form->skip_zero_click) { |
292 form->skip_zero_click = true; | 292 form->skip_zero_click = true; |
293 if (!UpdateLogin(*form, changes)) | 293 if (!UpdateLogin(*form, changes)) |
294 return false; | 294 return false; |
295 } | 295 } |
296 } | 296 } |
297 | 297 |
298 return true; | 298 return true; |
299 } | 299 } |
300 | 300 |
301 bool NativeBackendLibsecret::GetLogins( | 301 bool NativeBackendLibsecret::GetLogins( |
302 const PasswordStore::FormDigest& form, | 302 const PasswordStore::FormDigest& form, |
303 ScopedVector<autofill::PasswordForm>* forms) { | 303 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
304 return GetLoginsList(&form, ALL_LOGINS, forms); | 304 return GetLoginsList(&form, ALL_LOGINS, forms); |
305 } | 305 } |
306 | 306 |
307 bool NativeBackendLibsecret::AddUpdateLoginSearch( | 307 bool NativeBackendLibsecret::AddUpdateLoginSearch( |
308 const autofill::PasswordForm& lookup_form, | 308 const PasswordForm& lookup_form, |
309 ScopedVector<autofill::PasswordForm>* forms) { | 309 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
310 if (!ensured_keyring_unlocked_) { | 310 if (!ensured_keyring_unlocked_) { |
311 LibsecretLoader::EnsureKeyringUnlocked(); | 311 LibsecretLoader::EnsureKeyringUnlocked(); |
312 ensured_keyring_unlocked_ = true; | 312 ensured_keyring_unlocked_ = true; |
313 } | 313 } |
314 | 314 |
315 LibsecretAttributesBuilder attrs; | 315 LibsecretAttributesBuilder attrs; |
316 attrs.Append("origin_url", lookup_form.origin.spec()); | 316 attrs.Append("origin_url", lookup_form.origin.spec()); |
317 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element)); | 317 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element)); |
318 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value)); | 318 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value)); |
319 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element)); | 319 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 | 388 |
389 if (error) { | 389 if (error) { |
390 LOG(ERROR) << "Libsecret add raw login failed: " << error->message; | 390 LOG(ERROR) << "Libsecret add raw login failed: " << error->message; |
391 g_error_free(error); | 391 g_error_free(error); |
392 return false; | 392 return false; |
393 } | 393 } |
394 return true; | 394 return true; |
395 } | 395 } |
396 | 396 |
397 bool NativeBackendLibsecret::GetAutofillableLogins( | 397 bool NativeBackendLibsecret::GetAutofillableLogins( |
398 ScopedVector<autofill::PasswordForm>* forms) { | 398 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
399 return GetLoginsList(nullptr, AUTOFILLABLE_LOGINS, forms); | 399 return GetLoginsList(nullptr, AUTOFILLABLE_LOGINS, forms); |
400 } | 400 } |
401 | 401 |
402 bool NativeBackendLibsecret::GetBlacklistLogins( | 402 bool NativeBackendLibsecret::GetBlacklistLogins( |
403 ScopedVector<autofill::PasswordForm>* forms) { | 403 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
404 return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms); | 404 return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms); |
405 } | 405 } |
406 | 406 |
407 bool NativeBackendLibsecret::GetAllLogins( | 407 bool NativeBackendLibsecret::GetAllLogins( |
408 ScopedVector<autofill::PasswordForm>* forms) { | 408 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
409 return GetLoginsList(nullptr, ALL_LOGINS, forms); | 409 return GetLoginsList(nullptr, ALL_LOGINS, forms); |
410 } | 410 } |
411 | 411 |
412 bool NativeBackendLibsecret::GetLoginsList( | 412 bool NativeBackendLibsecret::GetLoginsList( |
413 const PasswordStore::FormDigest* lookup_form, | 413 const PasswordStore::FormDigest* lookup_form, |
414 GetLoginsListOptions options, | 414 GetLoginsListOptions options, |
415 ScopedVector<autofill::PasswordForm>* forms) { | 415 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
416 if (!ensured_keyring_unlocked_) { | 416 if (!ensured_keyring_unlocked_) { |
417 LibsecretLoader::EnsureKeyringUnlocked(); | 417 LibsecretLoader::EnsureKeyringUnlocked(); |
418 ensured_keyring_unlocked_ = true; | 418 ensured_keyring_unlocked_ = true; |
419 } | 419 } |
420 | 420 |
421 LibsecretAttributesBuilder attrs; | 421 LibsecretAttributesBuilder attrs; |
422 attrs.Append("application", app_string_); | 422 attrs.Append("application", app_string_); |
423 if (options != ALL_LOGINS) | 423 if (options != ALL_LOGINS) |
424 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS); | 424 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS); |
425 if (lookup_form && | 425 if (lookup_form && |
(...skipping 16 matching lines...) Expand all Loading... |
442 if (found) | 442 if (found) |
443 g_list_free(found); | 443 g_list_free(found); |
444 return false; | 444 return false; |
445 } | 445 } |
446 | 446 |
447 *forms = ConvertFormList(found, lookup_form); | 447 *forms = ConvertFormList(found, lookup_form); |
448 if (lookup_form) | 448 if (lookup_form) |
449 return true; | 449 return true; |
450 | 450 |
451 // Get rid of the forms with the same sync tags. | 451 // Get rid of the forms with the same sync tags. |
452 ScopedVector<autofill::PasswordForm> duplicates; | 452 std::vector<std::unique_ptr<PasswordForm>> duplicates; |
453 std::vector<std::vector<autofill::PasswordForm*>> tag_groups; | 453 std::vector<std::vector<PasswordForm*>> tag_groups; |
454 password_manager_util::FindDuplicates(forms, &duplicates, &tag_groups); | 454 password_manager_util::FindDuplicates(forms, &duplicates, &tag_groups); |
455 if (duplicates.empty()) | 455 if (duplicates.empty()) |
456 return true; | 456 return true; |
457 for (const auto& group : tag_groups) { | 457 for (const auto& group : tag_groups) { |
458 if (group.size() > 1) { | 458 if (group.size() > 1) { |
459 // There are duplicates. Readd the first form. AddLogin() is smart enough | 459 // There are duplicates. Readd the first form. AddLogin() is smart enough |
460 // to clean the previous ones. | 460 // to clean the previous ones. |
461 password_manager::PasswordStoreChangeList changes = AddLogin(*group[0]); | 461 password_manager::PasswordStoreChangeList changes = AddLogin(*group[0]); |
462 if (changes.empty() || | 462 if (changes.empty() || |
463 changes.back().type() != password_manager::PasswordStoreChange::ADD) | 463 changes.back().type() != password_manager::PasswordStoreChange::ADD) |
464 return false; | 464 return false; |
465 } | 465 } |
466 } | 466 } |
467 return true; | 467 return true; |
468 } | 468 } |
469 | 469 |
470 bool NativeBackendLibsecret::GetLoginsBetween( | 470 bool NativeBackendLibsecret::GetLoginsBetween( |
471 base::Time get_begin, | 471 base::Time get_begin, |
472 base::Time get_end, | 472 base::Time get_end, |
473 TimestampToCompare date_to_compare, | 473 TimestampToCompare date_to_compare, |
474 ScopedVector<autofill::PasswordForm>* forms) { | 474 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
475 forms->clear(); | 475 forms->clear(); |
476 ScopedVector<autofill::PasswordForm> all_forms; | 476 std::vector<std::unique_ptr<PasswordForm>> all_forms; |
477 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) | 477 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) |
478 return false; | 478 return false; |
479 | 479 |
480 base::Time autofill::PasswordForm::*date_member = | 480 base::Time PasswordForm::*date_member = date_to_compare == CREATION_TIMESTAMP |
481 date_to_compare == CREATION_TIMESTAMP | 481 ? &PasswordForm::date_created |
482 ? &autofill::PasswordForm::date_created | 482 : &PasswordForm::date_synced; |
483 : &autofill::PasswordForm::date_synced; | 483 for (std::unique_ptr<PasswordForm>& saved_form : all_forms) { |
484 for (auto*& saved_form : all_forms) { | 484 if (get_begin <= saved_form.get()->*date_member && |
485 if (get_begin <= saved_form->*date_member && | 485 (get_end.is_null() || saved_form.get()->*date_member < get_end)) { |
486 (get_end.is_null() || saved_form->*date_member < get_end)) { | 486 forms->push_back(std::move(saved_form)); |
487 forms->push_back(saved_form); | |
488 saved_form = nullptr; | |
489 } | 487 } |
490 } | 488 } |
491 | 489 |
492 return true; | 490 return true; |
493 } | 491 } |
494 | 492 |
495 bool NativeBackendLibsecret::RemoveLoginsBetween( | 493 bool NativeBackendLibsecret::RemoveLoginsBetween( |
496 base::Time get_begin, | 494 base::Time get_begin, |
497 base::Time get_end, | 495 base::Time get_end, |
498 TimestampToCompare date_to_compare, | 496 TimestampToCompare date_to_compare, |
499 password_manager::PasswordStoreChangeList* changes) { | 497 password_manager::PasswordStoreChangeList* changes) { |
500 DCHECK(changes); | 498 DCHECK(changes); |
501 changes->clear(); | 499 changes->clear(); |
502 ScopedVector<autofill::PasswordForm> forms; | 500 std::vector<std::unique_ptr<PasswordForm>> forms; |
503 if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms)) | 501 if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms)) |
504 return false; | 502 return false; |
505 | 503 |
506 for (size_t i = 0; i < forms.size(); ++i) { | 504 for (size_t i = 0; i < forms.size(); ++i) { |
507 if (!RemoveLogin(*forms[i], changes)) | 505 if (!RemoveLogin(*forms[i], changes)) |
508 return false; | 506 return false; |
509 } | 507 } |
510 return true; | 508 return true; |
511 } | 509 } |
512 | 510 |
513 ScopedVector<autofill::PasswordForm> NativeBackendLibsecret::ConvertFormList( | 511 std::vector<std::unique_ptr<PasswordForm>> |
| 512 NativeBackendLibsecret::ConvertFormList( |
514 GList* found, | 513 GList* found, |
515 const PasswordStore::FormDigest* lookup_form) { | 514 const PasswordStore::FormDigest* lookup_form) { |
516 ScopedVector<autofill::PasswordForm> forms; | 515 std::vector<std::unique_ptr<PasswordForm>> forms; |
517 password_manager::PSLDomainMatchMetric psl_domain_match_metric = | 516 password_manager::PSLDomainMatchMetric psl_domain_match_metric = |
518 password_manager::PSL_DOMAIN_MATCH_NONE; | 517 password_manager::PSL_DOMAIN_MATCH_NONE; |
519 GError* error = nullptr; | 518 GError* error = nullptr; |
520 const bool allow_psl_match = | 519 const bool allow_psl_match = |
521 lookup_form && password_manager::ShouldPSLDomainMatchingApply( | 520 lookup_form && password_manager::ShouldPSLDomainMatchingApply( |
522 password_manager::GetRegistryControlledDomain( | 521 password_manager::GetRegistryControlledDomain( |
523 GURL(lookup_form->signon_realm))); | 522 GURL(lookup_form->signon_realm))); |
524 for (GList* element = g_list_first(found); element != nullptr; | 523 for (GList* element = g_list_first(found); element != nullptr; |
525 element = g_list_next(element)) { | 524 element = g_list_next(element)) { |
526 SecretItem* secretItem = static_cast<SecretItem*>(element->data); | 525 SecretItem* secretItem = static_cast<SecretItem*>(element->data); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 if (lookup_form) { | 569 if (lookup_form) { |
571 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", | 570 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", |
572 allow_psl_match | 571 allow_psl_match |
573 ? psl_domain_match_metric | 572 ? psl_domain_match_metric |
574 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, | 573 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, |
575 password_manager::PSL_DOMAIN_MATCH_COUNT); | 574 password_manager::PSL_DOMAIN_MATCH_COUNT); |
576 } | 575 } |
577 g_list_free(found); | 576 g_list_free(found); |
578 return forms; | 577 return forms; |
579 } | 578 } |
OLD | NEW |