| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/password_store_mac.h" | 5 #include "chrome/browser/password_manager/password_store_mac.h" |
| 6 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 6 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
| 7 | 7 |
| 8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac_util.h" |
| 13 #include "base/stl_util-inl.h" | 14 #include "base/stl_util-inl.h" |
| 14 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 15 #include "chrome/browser/keychain_mac.h" | 16 #include "chrome/browser/keychain_mac.h" |
| 16 #include "chrome/browser/password_manager/login_database_mac.h" | 17 #include "chrome/browser/password_manager/login_database_mac.h" |
| 17 | 18 |
| 18 using webkit_glue::PasswordForm; | 19 using webkit_glue::PasswordForm; |
| 19 | 20 |
| 20 static const OSType kChromeKeychainCreatorCode = 'rimZ'; | |
| 21 | |
| 22 // Utility class to handle the details of constructing and running a keychain | 21 // Utility class to handle the details of constructing and running a keychain |
| 23 // search from a set of attributes. | 22 // search from a set of attributes. |
| 24 class KeychainSearch { | 23 class KeychainSearch { |
| 25 public: | 24 public: |
| 26 KeychainSearch(const MacKeychain& keychain); | 25 KeychainSearch(const MacKeychain& keychain); |
| 27 ~KeychainSearch(); | 26 ~KeychainSearch(); |
| 28 | 27 |
| 29 // Sets up a keycahin search based on an non "null" (NULL for char*, | 28 // Sets up a keycahin search based on an non "null" (NULL for char*, |
| 30 // The appropriate "Any" entry for other types) arguments. | 29 // The appropriate "Any" entry for other types) arguments. |
| 31 // | 30 // |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 database_blacklist_forms.begin(), | 430 database_blacklist_forms.begin(), |
| 432 database_blacklist_forms.end()); | 431 database_blacklist_forms.end()); |
| 433 | 432 |
| 434 // Clear out all the Keychain entries we used. | 433 // Clear out all the Keychain entries we used. |
| 435 DeleteVectorElementsInSet(keychain_forms, used_keychain_forms); | 434 DeleteVectorElementsInSet(keychain_forms, used_keychain_forms); |
| 436 } | 435 } |
| 437 | 436 |
| 438 std::vector<PasswordForm*> GetPasswordsForForms( | 437 std::vector<PasswordForm*> GetPasswordsForForms( |
| 439 const MacKeychain& keychain, std::vector<PasswordForm*>* database_forms) { | 438 const MacKeychain& keychain, std::vector<PasswordForm*>* database_forms) { |
| 440 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); | 439 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); |
| 441 | 440 |
| 442 std::vector<PasswordForm*> merged_forms; | 441 std::vector<PasswordForm*> merged_forms; |
| 443 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); | 442 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); |
| 444 i != database_forms->end();) { | 443 i != database_forms->end();) { |
| 445 std::vector<PasswordForm*> db_form_container(1, *i); | 444 std::vector<PasswordForm*> db_form_container(1, *i); |
| 446 std::vector<PasswordForm*> keychain_matches = | 445 std::vector<PasswordForm*> keychain_matches = |
| 447 keychain_adapter.PasswordsMergeableWithForm(**i); | 446 keychain_adapter.PasswordsMergeableWithForm(**i); |
| 448 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); | 447 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); |
| 449 if (db_form_container.size() == 0) { | 448 if (db_form_container.size() == 0) { |
| 450 i = database_forms->erase(i); | 449 i = database_forms->erase(i); |
| 451 } else { | 450 } else { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 return NULL; | 499 return NULL; |
| 501 } | 500 } |
| 502 | 501 |
| 503 std::vector<PasswordForm*> | 502 std::vector<PasswordForm*> |
| 504 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { | 503 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { |
| 505 SecAuthenticationType supported_auth_types[] = { | 504 SecAuthenticationType supported_auth_types[] = { |
| 506 kSecAuthenticationTypeHTMLForm, | 505 kSecAuthenticationTypeHTMLForm, |
| 507 kSecAuthenticationTypeHTTPBasic, | 506 kSecAuthenticationTypeHTTPBasic, |
| 508 kSecAuthenticationTypeHTTPDigest, | 507 kSecAuthenticationTypeHTTPDigest, |
| 509 }; | 508 }; |
| 510 OSType creator = finds_only_owned_ ? kChromeKeychainCreatorCode : 0; | |
| 511 | 509 |
| 512 std::vector<SecKeychainItemRef> matches; | 510 std::vector<SecKeychainItemRef> matches; |
| 513 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) { | 511 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) { |
| 514 KeychainSearch keychain_search(*keychain_); | 512 KeychainSearch keychain_search(*keychain_); |
| 515 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i], | 513 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i], |
| 516 NULL, NULL, NULL, creator); | 514 NULL, NULL, NULL, CreatorCodeForSearch()); |
| 517 keychain_search.FindMatchingItems(&matches); | 515 keychain_search.FindMatchingItems(&matches); |
| 518 } | 516 } |
| 519 | 517 |
| 520 return ConvertKeychainItemsToForms(&matches); | 518 return ConvertKeychainItemsToForms(&matches); |
| 521 } | 519 } |
| 522 | 520 |
| 523 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { | 521 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { |
| 524 // We should never be trying to store a blacklist in the keychain. | 522 // We should never be trying to store a blacklist in the keychain. |
| 525 DCHECK(!form.blacklisted_by_user); | 523 DCHECK(!form.blacklisted_by_user); |
| 526 | 524 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 540 SecKeychainItemRef new_item = NULL; | 538 SecKeychainItemRef new_item = NULL; |
| 541 OSStatus result = keychain_->AddInternetPassword( | 539 OSStatus result = keychain_->AddInternetPassword( |
| 542 NULL, server.size(), server.c_str(), | 540 NULL, server.size(), server.c_str(), |
| 543 security_domain.size(), security_domain.c_str(), | 541 security_domain.size(), security_domain.c_str(), |
| 544 username.size(), username.c_str(), | 542 username.size(), username.c_str(), |
| 545 path.size(), path.c_str(), | 543 path.size(), path.c_str(), |
| 546 port, protocol, AuthTypeForScheme(form.scheme), | 544 port, protocol, AuthTypeForScheme(form.scheme), |
| 547 password.size(), password.c_str(), &new_item); | 545 password.size(), password.c_str(), &new_item); |
| 548 | 546 |
| 549 if (result == noErr) { | 547 if (result == noErr) { |
| 550 SetKeychainItemCreatorCode(new_item, kChromeKeychainCreatorCode); | 548 SetKeychainItemCreatorCode(new_item, mac_util::CreatorCodeForApplication()); |
| 551 keychain_->Free(new_item); | 549 keychain_->Free(new_item); |
| 552 } else if (result == errSecDuplicateItem) { | 550 } else if (result == errSecDuplicateItem) { |
| 553 // If we collide with an existing item, find and update it instead. | 551 // If we collide with an existing item, find and update it instead. |
| 554 SecKeychainItemRef existing_item = KeychainItemForForm(form); | 552 SecKeychainItemRef existing_item = KeychainItemForForm(form); |
| 555 if (!existing_item) { | 553 if (!existing_item) { |
| 556 return false; | 554 return false; |
| 557 } | 555 } |
| 558 bool changed = SetKeychainItemPassword(existing_item, password); | 556 bool changed = SetKeychainItemPassword(existing_item, password); |
| 559 keychain_->Free(existing_item); | 557 keychain_->Free(existing_item); |
| 560 return changed; | 558 return changed; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 // TODO(stuartmorgan): Proxies will currently fail here, since their | 632 // TODO(stuartmorgan): Proxies will currently fail here, since their |
| 635 // signon_realm is not a URL. We need to detect the proxy case and handle | 633 // signon_realm is not a URL. We need to detect the proxy case and handle |
| 636 // it specially. | 634 // it specially. |
| 637 return matches; | 635 return matches; |
| 638 } | 636 } |
| 639 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 637 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
| 640 : kSecProtocolTypeHTTP; | 638 : kSecProtocolTypeHTTP; |
| 641 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); | 639 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); |
| 642 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? | 640 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? |
| 643 NULL : security_domain.c_str(); | 641 NULL : security_domain.c_str(); |
| 644 OSType creator = finds_only_owned_ ? kChromeKeychainCreatorCode : 0; | |
| 645 | |
| 646 KeychainSearch keychain_search(*keychain_); | 642 KeychainSearch keychain_search(*keychain_); |
| 647 keychain_search.Init(server.c_str(), port, protocol, auth_type, | 643 keychain_search.Init(server.c_str(), port, protocol, auth_type, |
| 648 auth_domain, path, username, creator); | 644 auth_domain, path, username, CreatorCodeForSearch()); |
| 649 keychain_search.FindMatchingItems(&matches); | 645 keychain_search.FindMatchingItems(&matches); |
| 650 return matches; | 646 return matches; |
| 651 } | 647 } |
| 652 | 648 |
| 653 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | 649 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. |
| 654 bool MacKeychainPasswordFormAdapter::ExtractSignonRealmComponents( | 650 bool MacKeychainPasswordFormAdapter::ExtractSignonRealmComponents( |
| 655 const std::string& signon_realm, std::string* server, int* port, | 651 const std::string& signon_realm, std::string* server, int* port, |
| 656 bool* is_secure, std::string* security_domain) { | 652 bool* is_secure, std::string* security_domain) { |
| 657 // The signon_realm will be the Origin portion of a URL for an HTML form, | 653 // The signon_realm will be the Origin portion of a URL for an HTML form, |
| 658 // and the same but with the security domain as a path for HTTP auth. | 654 // and the same but with the security domain as a path for HTTP auth. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 bool MacKeychainPasswordFormAdapter::SetKeychainItemCreatorCode( | 694 bool MacKeychainPasswordFormAdapter::SetKeychainItemCreatorCode( |
| 699 const SecKeychainItemRef& keychain_item, OSType creator_code) { | 695 const SecKeychainItemRef& keychain_item, OSType creator_code) { |
| 700 SecKeychainAttribute attr = { kSecCreatorItemAttr, sizeof(creator_code), | 696 SecKeychainAttribute attr = { kSecCreatorItemAttr, sizeof(creator_code), |
| 701 &creator_code }; | 697 &creator_code }; |
| 702 SecKeychainAttributeList attrList = { 1, &attr }; | 698 SecKeychainAttributeList attrList = { 1, &attr }; |
| 703 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, | 699 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, |
| 704 &attrList, 0, NULL); | 700 &attrList, 0, NULL); |
| 705 return result == noErr; | 701 return result == noErr; |
| 706 } | 702 } |
| 707 | 703 |
| 704 OSType MacKeychainPasswordFormAdapter::CreatorCodeForSearch() { |
| 705 return finds_only_owned_ ? mac_util::CreatorCodeForApplication() : 0; |
| 706 } |
| 707 |
| 708 #pragma mark - | 708 #pragma mark - |
| 709 | 709 |
| 710 PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain, | 710 PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain, |
| 711 LoginDatabaseMac* login_db) | 711 LoginDatabaseMac* login_db) |
| 712 : keychain_(keychain), login_metadata_db_(login_db) { | 712 : keychain_(keychain), login_metadata_db_(login_db) { |
| 713 DCHECK(keychain_.get()); | 713 DCHECK(keychain_.get()); |
| 714 DCHECK(login_metadata_db_.get()); | 714 DCHECK(login_metadata_db_.get()); |
| 715 } | 715 } |
| 716 | 716 |
| 717 PasswordStoreMac::~PasswordStoreMac() {} | 717 PasswordStoreMac::~PasswordStoreMac() {} |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 | 806 |
| 807 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { | 807 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { |
| 808 std::vector<PasswordForm*> database_forms; | 808 std::vector<PasswordForm*> database_forms; |
| 809 login_metadata_db_->GetBlacklistLogins(&database_forms); | 809 login_metadata_db_->GetBlacklistLogins(&database_forms); |
| 810 NotifyConsumer(request, database_forms); | 810 NotifyConsumer(request, database_forms); |
| 811 } | 811 } |
| 812 | 812 |
| 813 void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) { | 813 void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) { |
| 814 std::vector<PasswordForm*> database_forms; | 814 std::vector<PasswordForm*> database_forms; |
| 815 login_metadata_db_->GetAutofillableLogins(&database_forms); | 815 login_metadata_db_->GetAutofillableLogins(&database_forms); |
| 816 | 816 |
| 817 std::vector<PasswordForm*> merged_forms = | 817 std::vector<PasswordForm*> merged_forms = |
| 818 internal_keychain_helpers::GetPasswordsForForms(*keychain_, | 818 internal_keychain_helpers::GetPasswordsForForms(*keychain_, |
| 819 &database_forms); | 819 &database_forms); |
| 820 | 820 |
| 821 // Clean up any orphaned database entries. | 821 // Clean up any orphaned database entries. |
| 822 RemoveDatabaseForms(database_forms); | 822 RemoveDatabaseForms(database_forms); |
| 823 STLDeleteElements(&database_forms); | 823 STLDeleteElements(&database_forms); |
| 824 | 824 |
| 825 NotifyConsumer(request, merged_forms); | 825 NotifyConsumer(request, merged_forms); |
| 826 } | 826 } |
| 827 | 827 |
| 828 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { | 828 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { |
| 829 if (form.blacklisted_by_user) { | 829 if (form.blacklisted_by_user) { |
| 830 return true; | 830 return true; |
| 831 } | 831 } |
| 832 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); | 832 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); |
| 833 return keychainAdapter.AddPassword(form); | 833 return keychainAdapter.AddPassword(form); |
| 834 } | 834 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 846 break; | 846 break; |
| 847 } | 847 } |
| 848 } | 848 } |
| 849 STLDeleteElements(&database_forms); | 849 STLDeleteElements(&database_forms); |
| 850 return has_match; | 850 return has_match; |
| 851 } | 851 } |
| 852 | 852 |
| 853 std::vector<PasswordForm*> PasswordStoreMac::GetUnusedKeychainForms() { | 853 std::vector<PasswordForm*> PasswordStoreMac::GetUnusedKeychainForms() { |
| 854 std::vector<PasswordForm*> database_forms; | 854 std::vector<PasswordForm*> database_forms; |
| 855 login_metadata_db_->GetAutofillableLogins(&database_forms); | 855 login_metadata_db_->GetAutofillableLogins(&database_forms); |
| 856 | 856 |
| 857 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get()); | 857 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get()); |
| 858 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 858 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
| 859 std::vector<PasswordForm*> owned_keychain_forms = | 859 std::vector<PasswordForm*> owned_keychain_forms = |
| 860 owned_keychain_adapter.GetAllPasswordFormPasswords(); | 860 owned_keychain_adapter.GetAllPasswordFormPasswords(); |
| 861 | 861 |
| 862 // Run a merge; anything left in owned_keychain_forms when we are done no | 862 // Run a merge; anything left in owned_keychain_forms when we are done no |
| 863 // longer has a matching database entry. | 863 // longer has a matching database entry. |
| 864 std::vector<PasswordForm*> merged_forms; | 864 std::vector<PasswordForm*> merged_forms; |
| 865 internal_keychain_helpers::MergePasswordForms(&owned_keychain_forms, | 865 internal_keychain_helpers::MergePasswordForms(&owned_keychain_forms, |
| 866 &database_forms, | 866 &database_forms, |
| 867 &merged_forms); | 867 &merged_forms); |
| 868 STLDeleteElements(&merged_forms); | 868 STLDeleteElements(&merged_forms); |
| 869 STLDeleteElements(&database_forms); | 869 STLDeleteElements(&database_forms); |
| 870 | 870 |
| 871 return owned_keychain_forms; | 871 return owned_keychain_forms; |
| 872 } | 872 } |
| 873 | 873 |
| 874 void PasswordStoreMac::RemoveDatabaseForms( | 874 void PasswordStoreMac::RemoveDatabaseForms( |
| 875 const std::vector<PasswordForm*>& forms) { | 875 const std::vector<PasswordForm*>& forms) { |
| 876 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); | 876 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); |
| 877 i != forms.end(); ++i) { | 877 i != forms.end(); ++i) { |
| 878 login_metadata_db_->RemoveLogin(**i); | 878 login_metadata_db_->RemoveLogin(**i); |
| 879 } | 879 } |
| 880 } | 880 } |
| 881 | 881 |
| 882 void PasswordStoreMac::RemoveKeychainForms( | 882 void PasswordStoreMac::RemoveKeychainForms( |
| 883 const std::vector<PasswordForm*>& forms) { | 883 const std::vector<PasswordForm*>& forms) { |
| 884 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get()); | 884 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get()); |
| 885 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 885 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
| 886 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); | 886 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); |
| 887 i != forms.end(); ++i) { | 887 i != forms.end(); ++i) { |
| 888 owned_keychain_adapter.RemovePassword(**i); | 888 owned_keychain_adapter.RemovePassword(**i); |
| 889 } | 889 } |
| 890 } | 890 } |
| OLD | NEW |