| 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 <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <list> | 8 #include <list> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 } | 257 } |
| 258 | 258 |
| 259 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin( | 259 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin( |
| 260 const PasswordForm& form) { | 260 const PasswordForm& form) { |
| 261 // Based on LoginDatabase::AddLogin(), we search for an existing match based | 261 // Based on LoginDatabase::AddLogin(), we search for an existing match based |
| 262 // on origin_url, username_element, username_value, password_element, submit | 262 // on origin_url, username_element, username_value, password_element, submit |
| 263 // element, and signon_realm first, remove that, and then add the new entry. | 263 // element, and signon_realm first, remove that, and then add the new entry. |
| 264 // We'd add the new one first, and then delete the original, but then the | 264 // We'd add the new one first, and then delete the original, but then the |
| 265 // delete might actually delete the newly-added entry! | 265 // delete might actually delete the newly-added entry! |
| 266 ScopedVector<autofill::PasswordForm> forms; | 266 ScopedVector<autofill::PasswordForm> forms; |
| 267 AddUpdateLoginSearch(form, &forms.get(), SEARCH_USE_SUBMIT); | 267 AddUpdateLoginSearch(form, SEARCH_USE_SUBMIT, &forms); |
| 268 password_manager::PasswordStoreChangeList changes; | 268 password_manager::PasswordStoreChangeList changes; |
| 269 if (forms.size() > 0) { | 269 if (forms.size() > 0) { |
| 270 if (forms.size() > 1) { | 270 if (forms.size() > 1) { |
| 271 VLOG(1) << "Adding login when there are " << forms.size() | 271 VLOG(1) << "Adding login when there are " << forms.size() |
| 272 << " matching logins already! Will replace only the first."; | 272 << " matching logins already! Will replace only the first."; |
| 273 } | 273 } |
| 274 | 274 |
| 275 if (RemoveLogin(*forms[0])) { | 275 if (RemoveLogin(*forms[0])) { |
| 276 changes.push_back(password_manager::PasswordStoreChange( | 276 changes.push_back(password_manager::PasswordStoreChange( |
| 277 password_manager::PasswordStoreChange::REMOVE, *forms[0])); | 277 password_manager::PasswordStoreChange::REMOVE, *forms[0])); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 290 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by | 290 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by |
| 291 // origin_url, username_element, username_value, password_element, and | 291 // origin_url, username_element, username_value, password_element, and |
| 292 // signon_realm. We then compare the result to the updated form. If they | 292 // signon_realm. We then compare the result to the updated form. If they |
| 293 // differ in any of the mutable fields, then we remove the original, and | 293 // differ in any of the mutable fields, then we remove the original, and |
| 294 // then add the new entry. We'd add the new one first, and then delete the | 294 // then add the new entry. We'd add the new one first, and then delete the |
| 295 // original, but then the delete might actually delete the newly-added entry! | 295 // original, but then the delete might actually delete the newly-added entry! |
| 296 DCHECK(changes); | 296 DCHECK(changes); |
| 297 changes->clear(); | 297 changes->clear(); |
| 298 | 298 |
| 299 ScopedVector<autofill::PasswordForm> forms; | 299 ScopedVector<autofill::PasswordForm> forms; |
| 300 AddUpdateLoginSearch(form, &forms.get(), SEARCH_IGNORE_SUBMIT); | 300 AddUpdateLoginSearch(form, SEARCH_IGNORE_SUBMIT, &forms); |
| 301 | 301 |
| 302 bool removed = false; | 302 bool removed = false; |
| 303 for (size_t i = 0; i < forms.size(); ++i) { | 303 for (size_t i = 0; i < forms.size(); ++i) { |
| 304 if (*forms[i] != form) { | 304 if (*forms[i] != form) { |
| 305 RemoveLogin(*forms[i]); | 305 RemoveLogin(*forms[i]); |
| 306 removed = true; | 306 removed = true; |
| 307 } | 307 } |
| 308 } | 308 } |
| 309 if (!removed) | 309 if (!removed) |
| 310 return true; | 310 return true; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 changes); | 345 changes); |
| 346 } | 346 } |
| 347 | 347 |
| 348 bool NativeBackendLibsecret::RemoveLoginsSyncedBetween( | 348 bool NativeBackendLibsecret::RemoveLoginsSyncedBetween( |
| 349 base::Time delete_begin, | 349 base::Time delete_begin, |
| 350 base::Time delete_end, | 350 base::Time delete_end, |
| 351 password_manager::PasswordStoreChangeList* changes) { | 351 password_manager::PasswordStoreChangeList* changes) { |
| 352 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); | 352 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); |
| 353 } | 353 } |
| 354 | 354 |
| 355 bool NativeBackendLibsecret::GetLogins(const PasswordForm& form, | 355 bool NativeBackendLibsecret::GetLogins( |
| 356 PasswordFormList* forms) { | 356 const PasswordForm& form, |
| 357 return GetLoginsList(forms, &form, ALL_LOGINS); | 357 ScopedVector<autofill::PasswordForm>* forms) { |
| 358 return GetLoginsList(&form, ALL_LOGINS, forms); |
| 358 } | 359 } |
| 359 | 360 |
| 360 void NativeBackendLibsecret::AddUpdateLoginSearch( | 361 void NativeBackendLibsecret::AddUpdateLoginSearch( |
| 361 const autofill::PasswordForm& lookup_form, | 362 const autofill::PasswordForm& lookup_form, |
| 362 PasswordFormList* forms, | 363 AddUpdateLoginSearchOptions options, |
| 363 AddUpdateLoginSearchOptions options) { | 364 ScopedVector<autofill::PasswordForm>* forms) { |
| 364 LibsecretAttributesBuilder attrs; | 365 LibsecretAttributesBuilder attrs; |
| 365 attrs.Append("origin_url", lookup_form.origin.spec()); | 366 attrs.Append("origin_url", lookup_form.origin.spec()); |
| 366 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element)); | 367 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element)); |
| 367 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value)); | 368 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value)); |
| 368 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element)); | 369 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element)); |
| 369 if (options == SEARCH_USE_SUBMIT) | 370 if (options == SEARCH_USE_SUBMIT) |
| 370 attrs.Append("submit_element", UTF16ToUTF8(lookup_form.submit_element)); | 371 attrs.Append("submit_element", UTF16ToUTF8(lookup_form.submit_element)); |
| 371 attrs.Append("signon_realm", lookup_form.signon_realm); | 372 attrs.Append("signon_realm", lookup_form.signon_realm); |
| 372 attrs.Append("application", app_string_); | 373 attrs.Append("application", app_string_); |
| 373 | 374 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 "application", app_string_.c_str(), nullptr); | 420 "application", app_string_.c_str(), nullptr); |
| 420 | 421 |
| 421 if (error) { | 422 if (error) { |
| 422 VLOG(1) << "Libsecret add raw login failed: " << error->message; | 423 VLOG(1) << "Libsecret add raw login failed: " << error->message; |
| 423 g_error_free(error); | 424 g_error_free(error); |
| 424 return false; | 425 return false; |
| 425 } | 426 } |
| 426 return true; | 427 return true; |
| 427 } | 428 } |
| 428 | 429 |
| 429 bool NativeBackendLibsecret::GetAutofillableLogins(PasswordFormList* forms) { | 430 bool NativeBackendLibsecret::GetAutofillableLogins( |
| 430 return GetLoginsList(forms, nullptr, AUTOFILLABLE_LOGINS); | 431 ScopedVector<autofill::PasswordForm>* forms) { |
| 432 return GetLoginsList(nullptr, AUTOFILLABLE_LOGINS, forms); |
| 431 } | 433 } |
| 432 | 434 |
| 433 bool NativeBackendLibsecret::GetBlacklistLogins(PasswordFormList* forms) { | 435 bool NativeBackendLibsecret::GetBlacklistLogins( |
| 434 return GetLoginsList(forms, nullptr, BLACKLISTED_LOGINS); | 436 ScopedVector<autofill::PasswordForm>* forms) { |
| 437 return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms); |
| 435 } | 438 } |
| 436 | 439 |
| 437 bool NativeBackendLibsecret::GetLoginsList(PasswordFormList* forms, | 440 bool NativeBackendLibsecret::GetLoginsList( |
| 438 const PasswordForm* lookup_form, | 441 const PasswordForm* lookup_form, |
| 439 GetLoginsListOptions options) { | 442 GetLoginsListOptions options, |
| 443 ScopedVector<autofill::PasswordForm>* forms) { |
| 440 LibsecretAttributesBuilder attrs; | 444 LibsecretAttributesBuilder attrs; |
| 441 attrs.Append("application", app_string_); | 445 attrs.Append("application", app_string_); |
| 442 if (options != ALL_LOGINS) | 446 if (options != ALL_LOGINS) |
| 443 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS); | 447 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS); |
| 444 if (lookup_form && | 448 if (lookup_form && |
| 445 !password_manager::ShouldPSLDomainMatchingApply( | 449 !password_manager::ShouldPSLDomainMatchingApply( |
| 446 password_manager::GetRegistryControlledDomain( | 450 password_manager::GetRegistryControlledDomain( |
| 447 GURL(lookup_form->signon_realm)))) | 451 GURL(lookup_form->signon_realm)))) |
| 448 attrs.Append("signon_realm", lookup_form->signon_realm); | 452 attrs.Append("signon_realm", lookup_form->signon_realm); |
| 449 | 453 |
| 450 GError* error = nullptr; | 454 GError* error = nullptr; |
| 451 GList* found = secret_service_search_sync(nullptr, // default secret service | 455 GList* found = secret_service_search_sync(nullptr, // default secret service |
| 452 &kLibsecretSchema, attrs.Get(), | 456 &kLibsecretSchema, attrs.Get(), |
| 453 SECRET_SEARCH_ALL, | 457 SECRET_SEARCH_ALL, |
| 454 nullptr, // no cancellable ojbect | 458 nullptr, // no cancellable ojbect |
| 455 &error); | 459 &error); |
| 456 if (error) { | 460 if (error) { |
| 457 VLOG(1) << "Unable to get logins " << error->message; | 461 VLOG(1) << "Unable to get logins " << error->message; |
| 458 g_error_free(error); | 462 g_error_free(error); |
| 459 if (found) | 463 if (found) |
| 460 g_list_free(found); | 464 g_list_free(found); |
| 461 return false; | 465 return false; |
| 462 } | 466 } |
| 463 | 467 |
| 464 return ConvertFormList(found, lookup_form, forms); | 468 return ConvertFormList(found, lookup_form, forms); |
| 465 } | 469 } |
| 466 | 470 |
| 467 bool NativeBackendLibsecret::GetAllLogins(PasswordFormList* forms) { | 471 bool NativeBackendLibsecret::GetAllLogins( |
| 468 return GetLoginsList(forms, nullptr, ALL_LOGINS); | 472 ScopedVector<autofill::PasswordForm>* forms) { |
| 473 return GetLoginsList(nullptr, ALL_LOGINS, forms); |
| 469 } | 474 } |
| 470 | 475 |
| 471 bool NativeBackendLibsecret::GetLoginsBetween( | 476 bool NativeBackendLibsecret::GetLoginsBetween( |
| 472 base::Time get_begin, | 477 base::Time get_begin, |
| 473 base::Time get_end, | 478 base::Time get_end, |
| 474 TimestampToCompare date_to_compare, | 479 TimestampToCompare date_to_compare, |
| 475 PasswordFormList* forms) { | 480 ScopedVector<autofill::PasswordForm>* forms) { |
| 476 PasswordFormList all_forms; | 481 ScopedVector<autofill::PasswordForm> all_forms; |
| 477 if (!GetAllLogins(&all_forms)) | 482 if (!GetAllLogins(&all_forms)) |
| 478 return false; | 483 return false; |
| 479 | 484 |
| 480 base::Time autofill::PasswordForm::*date_member = | 485 base::Time autofill::PasswordForm::*date_member = |
| 481 date_to_compare == CREATION_TIMESTAMP | 486 date_to_compare == CREATION_TIMESTAMP |
| 482 ? &autofill::PasswordForm::date_created | 487 ? &autofill::PasswordForm::date_created |
| 483 : &autofill::PasswordForm::date_synced; | 488 : &autofill::PasswordForm::date_synced; |
| 484 for (size_t i = 0; i < all_forms.size(); ++i) { | 489 for (auto& saved_form : all_forms) { |
| 485 if (get_begin <= all_forms[i]->*date_member && | 490 if (get_begin <= saved_form->*date_member && |
| 486 (get_end.is_null() || all_forms[i]->*date_member < get_end)) { | 491 (get_end.is_null() || saved_form->*date_member < get_end)) { |
| 487 forms->push_back(all_forms[i]); | 492 forms->push_back(saved_form); |
| 488 } else { | 493 saved_form = nullptr; |
| 489 delete all_forms[i]; | |
| 490 } | 494 } |
| 491 } | 495 } |
| 492 | 496 |
| 493 return true; | 497 return true; |
| 494 } | 498 } |
| 495 | 499 |
| 496 bool NativeBackendLibsecret::RemoveLoginsBetween( | 500 bool NativeBackendLibsecret::RemoveLoginsBetween( |
| 497 base::Time get_begin, | 501 base::Time get_begin, |
| 498 base::Time get_end, | 502 base::Time get_end, |
| 499 TimestampToCompare date_to_compare, | 503 TimestampToCompare date_to_compare, |
| 500 password_manager::PasswordStoreChangeList* changes) { | 504 password_manager::PasswordStoreChangeList* changes) { |
| 501 DCHECK(changes); | 505 DCHECK(changes); |
| 502 changes->clear(); | 506 changes->clear(); |
| 503 ScopedVector<autofill::PasswordForm> forms; | 507 ScopedVector<autofill::PasswordForm> forms; |
| 504 if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms.get())) | 508 if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms)) |
| 505 return false; | 509 return false; |
| 506 | 510 |
| 507 bool ok = true; | 511 bool ok = true; |
| 508 for (size_t i = 0; i < forms.size(); ++i) { | 512 for (size_t i = 0; i < forms.size(); ++i) { |
| 509 if (RemoveLogin(*forms[i])) { | 513 if (RemoveLogin(*forms[i])) { |
| 510 changes->push_back(password_manager::PasswordStoreChange( | 514 changes->push_back(password_manager::PasswordStoreChange( |
| 511 password_manager::PasswordStoreChange::REMOVE, *forms[i])); | 515 password_manager::PasswordStoreChange::REMOVE, *forms[i])); |
| 512 } else { | 516 } else { |
| 513 ok = false; | 517 ok = false; |
| 514 } | 518 } |
| 515 } | 519 } |
| 516 return ok; | 520 return ok; |
| 517 } | 521 } |
| 518 | 522 |
| 519 bool NativeBackendLibsecret::ConvertFormList( | 523 bool NativeBackendLibsecret::ConvertFormList( |
| 520 GList* found, | 524 GList* found, |
| 521 const PasswordForm* lookup_form, | 525 const PasswordForm* lookup_form, |
| 522 NativeBackendLibsecret::PasswordFormList* forms) { | 526 ScopedVector<autofill::PasswordForm>* forms) { |
| 523 password_manager::PSLDomainMatchMetric psl_domain_match_metric = | 527 password_manager::PSLDomainMatchMetric psl_domain_match_metric = |
| 524 password_manager::PSL_DOMAIN_MATCH_NONE; | 528 password_manager::PSL_DOMAIN_MATCH_NONE; |
| 525 GError* error = nullptr; | 529 GError* error = nullptr; |
| 526 for (GList* element = g_list_first(found); element != nullptr; | 530 for (GList* element = g_list_first(found); element != nullptr; |
| 527 element = g_list_next(element)) { | 531 element = g_list_next(element)) { |
| 528 SecretItem* secretItem = static_cast<SecretItem*>(element->data); | 532 SecretItem* secretItem = static_cast<SecretItem*>(element->data); |
| 529 LibsecretLoader::secret_item_load_secret_sync(secretItem, nullptr, &error); | 533 LibsecretLoader::secret_item_load_secret_sync(secretItem, nullptr, &error); |
| 530 if (error) { | 534 if (error) { |
| 531 VLOG(1) << "Unable to load secret item" << error->message; | 535 VLOG(1) << "Unable to load secret item" << error->message; |
| 532 g_error_free(error); | 536 g_error_free(error); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 return true; | 582 return true; |
| 579 } | 583 } |
| 580 | 584 |
| 581 std::string NativeBackendLibsecret::GetProfileSpecificAppString( | 585 std::string NativeBackendLibsecret::GetProfileSpecificAppString( |
| 582 LocalProfileId id) { | 586 LocalProfileId id) { |
| 583 // Originally, the application string was always just "chrome" and used only | 587 // Originally, the application string was always just "chrome" and used only |
| 584 // so that we had *something* to search for since GNOME Keyring won't search | 588 // so that we had *something* to search for since GNOME Keyring won't search |
| 585 // for nothing. Now we use it to distinguish passwords for different profiles. | 589 // for nothing. Now we use it to distinguish passwords for different profiles. |
| 586 return base::StringPrintf("%s-%d", kLibsecretAppString, id); | 590 return base::StringPrintf("%s-%d", kLibsecretAppString, id); |
| 587 } | 591 } |
| OLD | NEW |