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/stl_util-inl.h" | 13 #include "base/stl_util-inl.h" |
14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
15 #include "base/time.h" | 15 #include "base/time.h" |
16 #include "chrome/browser/keychain_mac.h" | 16 #include "chrome/browser/keychain_mac.h" |
17 #include "chrome/browser/password_manager/login_database_mac.h" | 17 #include "chrome/browser/password_manager/login_database_mac.h" |
18 | 18 |
19 using webkit_glue::PasswordForm; | 19 using webkit_glue::PasswordForm; |
20 | 20 |
21 static const OSType kChromeKeychainCreatorCode = 'GCHR'; | |
22 | |
21 // Utility class to handle the details of constructing and running a keychain | 23 // Utility class to handle the details of constructing and running a keychain |
22 // search from a set of attributes. | 24 // search from a set of attributes. |
23 class KeychainSearch { | 25 class KeychainSearch { |
24 public: | 26 public: |
25 KeychainSearch(const MacKeychain& keychain); | 27 KeychainSearch(const MacKeychain& keychain); |
26 ~KeychainSearch(); | 28 ~KeychainSearch(); |
27 | 29 |
28 // Sets up a keycahin search based on an non "null" (NULL for char*, | 30 // Sets up a keycahin search based on an non "null" (NULL for char*, |
29 // The appropriate "Any" entry for other types) arguments. | 31 // The appropriate "Any" entry for other types) arguments. |
30 // | 32 // |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 bool is_secure; | 534 bool is_secure; |
533 if (!internal_keychain_helpers::ExtractSignonRealmComponents( | 535 if (!internal_keychain_helpers::ExtractSignonRealmComponents( |
534 form.signon_realm, &server, &port, &is_secure, &security_domain)) { | 536 form.signon_realm, &server, &port, &is_secure, &security_domain)) { |
535 return false; | 537 return false; |
536 } | 538 } |
537 std::string username = WideToUTF8(form.username_value); | 539 std::string username = WideToUTF8(form.username_value); |
538 std::string password = WideToUTF8(form.password_value); | 540 std::string password = WideToUTF8(form.password_value); |
539 std::string path = form.origin.path(); | 541 std::string path = form.origin.path(); |
540 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 542 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
541 : kSecProtocolTypeHTTP; | 543 : kSecProtocolTypeHTTP; |
544 SecKeychainItemRef new_item = NULL; | |
542 OSStatus result = keychain_->AddInternetPassword( | 545 OSStatus result = keychain_->AddInternetPassword( |
543 NULL, server.size(), server.c_str(), | 546 NULL, server.size(), server.c_str(), |
544 security_domain.size(), security_domain.c_str(), | 547 security_domain.size(), security_domain.c_str(), |
545 username.size(), username.c_str(), | 548 username.size(), username.c_str(), |
546 path.size(), path.c_str(), | 549 path.size(), path.c_str(), |
547 port, protocol, internal_keychain_helpers::AuthTypeForScheme(form.scheme), | 550 port, protocol, internal_keychain_helpers::AuthTypeForScheme(form.scheme), |
548 password.size(), password.c_str(), NULL); | 551 password.size(), password.c_str(), &new_item); |
552 | |
553 if (result == noErr) { | |
554 SetKeychainItemCreatorCode(new_item, kChromeKeychainCreatorCode); | |
555 keychain_->Free(new_item); | |
556 } | |
549 | 557 |
550 // If we collide with an existing item, find and update it instead. | 558 // If we collide with an existing item, find and update it instead. |
551 if (result == errSecDuplicateItem) { | 559 if (result == errSecDuplicateItem) { |
Mark Mentovai
2009/07/02 03:03:33
This ought to be |else if| now.
| |
552 SecKeychainItemRef existing_item = | 560 SecKeychainItemRef existing_item = |
553 internal_keychain_helpers::MatchingKeychainItem(*keychain_, form); | 561 internal_keychain_helpers::MatchingKeychainItem(*keychain_, form); |
554 if (!existing_item) { | 562 if (!existing_item) { |
555 return false; | 563 return false; |
556 } | 564 } |
557 bool changed = SetKeychainItemPassword(existing_item, password); | 565 bool changed = SetKeychainItemPassword(existing_item, password); |
558 keychain_->Free(existing_item); | 566 keychain_->Free(existing_item); |
559 return changed; | 567 return changed; |
560 } | 568 } |
561 | 569 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 } | 620 } |
613 | 621 |
614 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword( | 622 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword( |
615 const SecKeychainItemRef& keychain_item, const std::string& password) { | 623 const SecKeychainItemRef& keychain_item, const std::string& password) { |
616 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL, | 624 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL, |
617 password.size(), | 625 password.size(), |
618 password.c_str()); | 626 password.c_str()); |
619 return (result == noErr); | 627 return (result == noErr); |
620 } | 628 } |
621 | 629 |
630 bool MacKeychainPasswordFormAdapter::SetKeychainItemCreatorCode( | |
631 const SecKeychainItemRef& keychain_item, OSType creator_code) { | |
632 SecKeychainAttribute attr = { kSecCreatorItemAttr, sizeof(creator_code), | |
633 &creator_code }; | |
634 SecKeychainAttributeList attrList = { 1, &attr }; | |
635 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, | |
636 &attrList, 0, NULL); | |
637 return (result == noErr); | |
Mark Mentovai
2009/07/02 03:03:33
Parens aren't necessary here or in the preceding f
| |
638 } | |
639 | |
622 #pragma mark - | 640 #pragma mark - |
623 | 641 |
624 PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain, | 642 PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain, |
625 LoginDatabaseMac* login_db) | 643 LoginDatabaseMac* login_db) |
626 : keychain_(keychain), login_metadata_db_(login_db) { | 644 : keychain_(keychain), login_metadata_db_(login_db) { |
627 DCHECK(keychain_.get()); | 645 DCHECK(keychain_.get()); |
628 DCHECK(login_metadata_db_.get()); | 646 DCHECK(login_metadata_db_.get()); |
629 } | 647 } |
630 | 648 |
631 PasswordStoreMac::~PasswordStoreMac() {} | 649 PasswordStoreMac::~PasswordStoreMac() {} |
632 | 650 |
633 void PasswordStoreMac::AddLoginImpl(const PasswordForm& form) { | 651 void PasswordStoreMac::AddLoginImpl(const PasswordForm& form) { |
634 NOTIMPLEMENTED(); | 652 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); |
653 if (keychainAdapter.AddLogin(form)) { | |
654 login_metadata_db_->AddLogin(form); | |
655 } | |
635 } | 656 } |
636 | 657 |
637 void PasswordStoreMac::UpdateLoginImpl(const PasswordForm& form) { | 658 void PasswordStoreMac::UpdateLoginImpl(const PasswordForm& form) { |
638 NOTIMPLEMENTED(); | 659 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); |
660 // The keychain AddLogin will update if there is a collision and add if there | |
661 // isn't, which is the behavior we want, so there's no separate UpdateLogin. | |
662 if (keychainAdapter.AddLogin(form)) { | |
663 int update_count = 0; | |
664 login_metadata_db_->UpdateLogin(form, &update_count); | |
665 // Update will catch any database entries that we already had, but we could | |
666 // also be updating a keychain-only form, in which case we need to add. | |
667 if (update_count == 0) { | |
668 login_metadata_db_->AddLogin(form); | |
669 } | |
670 } | |
639 } | 671 } |
640 | 672 |
641 void PasswordStoreMac::RemoveLoginImpl(const PasswordForm& form) { | 673 void PasswordStoreMac::RemoveLoginImpl(const PasswordForm& form) { |
642 NOTIMPLEMENTED(); | 674 NOTIMPLEMENTED(); |
643 } | 675 } |
644 | 676 |
645 void PasswordStoreMac::GetLoginsImpl(GetLoginsRequest* request) { | 677 void PasswordStoreMac::GetLoginsImpl(GetLoginsRequest* request) { |
646 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); | 678 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); |
647 std::vector<PasswordForm*> keychain_forms = | 679 std::vector<PasswordForm*> keychain_forms = |
648 keychainAdapter.PasswordsMatchingForm(request->form); | 680 keychainAdapter.PasswordsMatchingForm(request->form); |
(...skipping 10 matching lines...) Expand all Loading... | |
659 for (std::vector<PasswordForm*>::iterator i = database_forms.begin(); | 691 for (std::vector<PasswordForm*>::iterator i = database_forms.begin(); |
660 i != database_forms.end(); ++i) { | 692 i != database_forms.end(); ++i) { |
661 login_metadata_db_->RemoveLogin(**i); | 693 login_metadata_db_->RemoveLogin(**i); |
662 } | 694 } |
663 // Delete the forms we aren't returning. | 695 // Delete the forms we aren't returning. |
664 STLDeleteElements(&database_forms); | 696 STLDeleteElements(&database_forms); |
665 STLDeleteElements(&keychain_forms); | 697 STLDeleteElements(&keychain_forms); |
666 | 698 |
667 NotifyConsumer(request, merged_forms); | 699 NotifyConsumer(request, merged_forms); |
668 } | 700 } |
OLD | NEW |