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/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 <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 #include <utility> | |
11 #include <vector> | 12 #include <vector> |
12 | 13 |
13 #include "base/callback.h" | 14 #include "base/callback.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/mac/mac_logging.h" | 16 #include "base/mac/mac_logging.h" |
16 #include "base/mac/mac_util.h" | 17 #include "base/mac/mac_util.h" |
17 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
18 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
19 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
20 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 switch (auth_type) { | 227 switch (auth_type) { |
227 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML; | 228 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML; |
228 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC; | 229 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC; |
229 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST; | 230 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST; |
230 default: return PasswordForm::SCHEME_OTHER; | 231 default: return PasswordForm::SCHEME_OTHER; |
231 } | 232 } |
232 } | 233 } |
233 | 234 |
234 bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain, | 235 bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain, |
235 const SecKeychainItemRef& keychain_item, | 236 const SecKeychainItemRef& keychain_item, |
236 PasswordForm* form) { | 237 PasswordForm* form, |
238 bool extract_password_data) { | |
237 DCHECK(form); | 239 DCHECK(form); |
238 | 240 |
239 SecKeychainAttributeInfo attrInfo; | 241 SecKeychainAttributeInfo attrInfo; |
240 UInt32 tags[] = { kSecAccountItemAttr, | 242 UInt32 tags[] = { kSecAccountItemAttr, |
241 kSecServerItemAttr, | 243 kSecServerItemAttr, |
242 kSecPortItemAttr, | 244 kSecPortItemAttr, |
243 kSecPathItemAttr, | 245 kSecPathItemAttr, |
244 kSecProtocolItemAttr, | 246 kSecProtocolItemAttr, |
245 kSecAuthenticationTypeItemAttr, | 247 kSecAuthenticationTypeItemAttr, |
246 kSecSecurityDomainItemAttr, | 248 kSecSecurityDomainItemAttr, |
247 kSecCreationDateItemAttr, | 249 kSecCreationDateItemAttr, |
248 kSecNegativeItemAttr }; | 250 kSecNegativeItemAttr }; |
249 attrInfo.count = arraysize(tags); | 251 attrInfo.count = arraysize(tags); |
250 attrInfo.tag = tags; | 252 attrInfo.tag = tags; |
251 attrInfo.format = NULL; | 253 attrInfo.format = NULL; |
252 | 254 |
253 SecKeychainAttributeList *attrList; | 255 SecKeychainAttributeList *attrList; |
254 UInt32 password_length; | 256 UInt32 password_length; |
255 void* password_data; | 257 |
258 // If |extract_password_data| is false, do not pass in a reference to | |
259 // |password_data|. ItemCopyAttributesAndData will then extract only the | |
260 // attributes of |keychain_item| (doesn't require OS authorization), and not | |
261 // attempt to extract its password data (requires OS authorization). | |
262 void* password_data = NULL; | |
263 void** password_data_ref = extract_password_data ? &password_data : NULL; | |
264 | |
256 OSStatus result = keychain.ItemCopyAttributesAndData(keychain_item, &attrInfo, | 265 OSStatus result = keychain.ItemCopyAttributesAndData(keychain_item, &attrInfo, |
257 NULL, &attrList, | 266 NULL, &attrList, |
258 &password_length, | 267 &password_length, |
259 &password_data); | 268 password_data_ref); |
260 | 269 |
261 if (result != noErr) { | 270 if (result != noErr) { |
262 // We don't log errSecAuthFailed because that just means that the user | 271 // We don't log errSecAuthFailed because that just means that the user |
263 // chose not to allow us access to the item. | 272 // chose not to allow us access to the item. |
264 if (result != errSecAuthFailed) { | 273 if (result != errSecAuthFailed) { |
265 OSSTATUS_LOG(ERROR, result) << "Keychain data load failed"; | 274 OSSTATUS_LOG(ERROR, result) << "Keychain data load failed"; |
266 } | 275 } |
267 return false; | 276 return false; |
268 } | 277 } |
269 | 278 |
270 UTF8ToUTF16(static_cast<const char *>(password_data), password_length, | 279 if (extract_password_data) { |
271 &(form->password_value)); | 280 UTF8ToUTF16(static_cast<const char *>(password_data), password_length, |
281 &(form->password_value)); | |
282 } | |
272 | 283 |
273 int port = kAnyPort; | 284 int port = kAnyPort; |
274 std::string server; | 285 std::string server; |
275 std::string security_domain; | 286 std::string security_domain; |
276 std::string path; | 287 std::string path; |
277 for (unsigned int i = 0; i < attrList->count; i++) { | 288 for (unsigned int i = 0; i < attrList->count; i++) { |
278 SecKeychainAttribute attr = attrList->attr[i]; | 289 SecKeychainAttribute attr = attrList->attr[i]; |
279 if (!attr.data) { | 290 if (!attr.data) { |
280 continue; | 291 continue; |
281 } | 292 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 form->blacklisted_by_user = true; | 334 form->blacklisted_by_user = true; |
324 } | 335 } |
325 break; | 336 break; |
326 } | 337 } |
327 } | 338 } |
328 keychain.ItemFreeAttributesAndData(attrList, password_data); | 339 keychain.ItemFreeAttributesAndData(attrList, password_data); |
329 | 340 |
330 // kSecNegativeItemAttr doesn't seem to actually be in widespread use. In | 341 // kSecNegativeItemAttr doesn't seem to actually be in widespread use. In |
331 // practice, other browsers seem to use a "" or " " password (and a special | 342 // practice, other browsers seem to use a "" or " " password (and a special |
332 // user name) to indicated blacklist entries. | 343 // user name) to indicated blacklist entries. |
333 if (form->password_value.empty() || EqualsASCII(form->password_value, " ")) { | 344 if (extract_password_data && (form->password_value.empty() || |
345 EqualsASCII(form->password_value, " "))) { | |
334 form->blacklisted_by_user = true; | 346 form->blacklisted_by_user = true; |
335 } | 347 } |
336 | 348 |
337 form->origin = URLFromComponents(form->ssl_valid, server, port, path); | 349 form->origin = URLFromComponents(form->ssl_valid, server, port, path); |
338 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm | 350 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm |
339 // format. | 351 // format. |
340 form->signon_realm = form->origin.GetOrigin().spec(); | 352 form->signon_realm = form->origin.GetOrigin().spec(); |
341 if (form->scheme != PasswordForm::SCHEME_HTML) { | 353 if (form->scheme != PasswordForm::SCHEME_HTML) { |
342 form->signon_realm.append(security_domain); | 354 form->signon_realm.append(security_domain); |
343 } | 355 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 | 448 |
437 // Add in the blacklist entries from the database. | 449 // Add in the blacklist entries from the database. |
438 merged_forms->insert(merged_forms->end(), | 450 merged_forms->insert(merged_forms->end(), |
439 database_blacklist_forms.begin(), | 451 database_blacklist_forms.begin(), |
440 database_blacklist_forms.end()); | 452 database_blacklist_forms.end()); |
441 | 453 |
442 // Clear out all the Keychain entries we used. | 454 // Clear out all the Keychain entries we used. |
443 DeleteVectorElementsInSet(keychain_forms, used_keychain_forms); | 455 DeleteVectorElementsInSet(keychain_forms, used_keychain_forms); |
444 } | 456 } |
445 | 457 |
458 std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( | |
459 std::vector<SecKeychainItemRef>* keychain_items, | |
460 const AppleKeychain& keychain) { | |
461 DCHECK(keychain_items); | |
462 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); | |
stuartmorgan
2013/10/09 23:49:25
It feels weird that this uses the form adapter ins
Raghu Simha
2013/10/10 00:32:19
SGTM.
| |
463 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems(); | |
464 std::vector<ItemFormPair> item_form_pairs; | |
465 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items->begin(); | |
466 i != keychain_items->end(); ++i) { | |
467 PasswordForm* form_without_password = new PasswordForm(); | |
468 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | |
469 keychain, | |
470 *i, | |
471 form_without_password, | |
472 false); // Load password attributes, but not password data. | |
473 item_form_pairs.push_back(std::make_pair(&(*i), form_without_password)); | |
474 } | |
475 return item_form_pairs; | |
476 } | |
477 | |
446 std::vector<PasswordForm*> GetPasswordsForForms( | 478 std::vector<PasswordForm*> GetPasswordsForForms( |
447 const AppleKeychain& keychain, | 479 const AppleKeychain& keychain, |
448 std::vector<PasswordForm*>* database_forms) { | 480 std::vector<PasswordForm*>* database_forms) { |
449 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); | 481 // First load the attributes of all items in the keychain without loading |
482 // their password data, and then match items in |database_forms| against them. | |
483 // This avoids individually searching through the keychain for passwords | |
484 // matching each form in |database_forms|, and results in a significant | |
485 // performance gain, replacing O(N) keychain search operations with a single | |
486 // operation that loads all keychain items, and then selective reads of only | |
487 // the relevant passwords. See crbug.com/263685. | |
488 std::vector<SecKeychainItemRef> keychain_items; | |
489 std::vector<ItemFormPair> item_form_pairs = | |
490 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items, | |
491 keychain); | |
450 | 492 |
493 // Next, compare the attributes of the PasswordForms in |database_forms| | |
494 // against those in |item_form_pairs|, and extract password data for each | |
495 // matching PasswordForm using its corresponding SecKeychainItemRef. | |
451 std::vector<PasswordForm*> merged_forms; | 496 std::vector<PasswordForm*> merged_forms; |
452 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); | 497 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); |
453 i != database_forms->end();) { | 498 i != database_forms->end();) { |
454 std::vector<PasswordForm*> db_form_container(1, *i); | 499 std::vector<PasswordForm*> db_form_container(1, *i); |
455 std::vector<PasswordForm*> keychain_matches = | 500 std::vector<PasswordForm*> keychain_matches = |
456 keychain_adapter.PasswordsMergeableWithForm(**i); | 501 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, **i); |
457 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); | 502 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); |
458 if (db_form_container.empty()) { | 503 if (db_form_container.empty()) { |
459 i = database_forms->erase(i); | 504 i = database_forms->erase(i); |
460 } else { | 505 } else { |
461 ++i; | 506 ++i; |
462 } | 507 } |
463 STLDeleteElements(&keychain_matches); | 508 STLDeleteElements(&keychain_matches); |
464 } | 509 } |
510 | |
511 // Clean up temporary PasswordForms and SecKeychainItemRefs. | |
512 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), | |
513 item_form_pairs.end()); | |
514 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin(); | |
515 i != keychain_items.end(); ++i) { | |
516 keychain.Free(*i); | |
517 } | |
465 return merged_forms; | 518 return merged_forms; |
466 } | 519 } |
467 | 520 |
521 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | |
522 bool ExtractSignonRealmComponents( | |
523 const std::string& signon_realm, std::string* server, int* port, | |
524 bool* is_secure, std::string* security_domain) { | |
525 // The signon_realm will be the Origin portion of a URL for an HTML form, | |
526 // and the same but with the security domain as a path for HTTP auth. | |
527 GURL realm_as_url(signon_realm); | |
528 if (!realm_as_url.is_valid()) { | |
529 return false; | |
530 } | |
531 | |
532 if (server) | |
533 *server = realm_as_url.host(); | |
534 if (is_secure) | |
535 *is_secure = realm_as_url.SchemeIsSecure(); | |
536 if (port) | |
537 *port = realm_as_url.has_port() ? atoi(realm_as_url.port().c_str()) : 0; | |
538 if (security_domain) { | |
539 // Strip the leading '/' off of the path to get the security domain. | |
540 if (realm_as_url.path().length() > 0) | |
541 *security_domain = realm_as_url.path().substr(1); | |
542 else | |
543 security_domain->clear(); | |
544 } | |
545 return true; | |
546 } | |
547 | |
548 bool FormIsValidAndMatchesOtherForm(const PasswordForm& query_form, | |
549 const PasswordForm& other_form) { | |
550 std::string server; | |
551 std::string security_domain; | |
552 int port; | |
553 bool is_secure; | |
554 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port, | |
555 &is_secure, &security_domain)) { | |
556 return false; | |
557 } | |
558 return internal_keychain_helpers::FormsMatchForMerge(query_form, other_form); | |
559 } | |
560 | |
561 std::vector<PasswordForm*> ExtractPasswordsMergeableWithForm( | |
562 const AppleKeychain& keychain, | |
563 const std::vector<ItemFormPair>& item_form_pairs, | |
564 const PasswordForm& query_form) { | |
565 std::vector<PasswordForm*> matches; | |
566 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); | |
567 i != item_form_pairs.end(); ++i) { | |
568 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { | |
569 // Create a new object, since the caller is responsible for deleting the | |
570 // returned forms. | |
571 PasswordForm* form_with_password = new PasswordForm(); | |
572 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | |
573 keychain, | |
574 *(i->first), | |
575 form_with_password, | |
576 true); // Load password attributes and data. | |
577 // Do not include blacklisted items found in the keychain. | |
578 if (form_with_password->blacklisted_by_user) | |
579 delete form_with_password; | |
stuartmorgan
2013/10/09 23:49:25
Since adding is conditional, it seems like it woul
Raghu Simha
2013/10/10 00:32:19
Done.
| |
580 else | |
581 matches.push_back(form_with_password); | |
582 } | |
583 } | |
584 return matches; | |
585 } | |
586 | |
468 } // namespace internal_keychain_helpers | 587 } // namespace internal_keychain_helpers |
469 | 588 |
470 #pragma mark - | 589 #pragma mark - |
471 | 590 |
472 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( | 591 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( |
473 const AppleKeychain* keychain) | 592 const AppleKeychain* keychain) |
474 : keychain_(keychain), finds_only_owned_(false) { | 593 : keychain_(keychain), finds_only_owned_(false) { |
475 } | 594 } |
476 | 595 |
477 std::vector<PasswordForm*> | 596 std::vector<PasswordForm*> |
478 MacKeychainPasswordFormAdapter::PasswordsFillingForm( | 597 MacKeychainPasswordFormAdapter::PasswordsFillingForm( |
479 const PasswordForm& query_form) { | 598 const PasswordForm& query_form) { |
480 std::vector<SecKeychainItemRef> keychain_items = | 599 std::vector<SecKeychainItemRef> keychain_items = |
481 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, | 600 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, |
482 NULL, NULL); | 601 NULL, NULL); |
483 | 602 |
484 return ConvertKeychainItemsToForms(&keychain_items); | 603 return ConvertKeychainItemsToForms(&keychain_items); |
485 } | 604 } |
486 | 605 |
487 std::vector<PasswordForm*> | |
488 MacKeychainPasswordFormAdapter::PasswordsMergeableWithForm( | |
489 const PasswordForm& query_form) { | |
490 std::string username = UTF16ToUTF8(query_form.username_value); | |
491 std::vector<SecKeychainItemRef> keychain_items = | |
492 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, | |
493 NULL, username.c_str()); | |
494 | |
495 return ConvertKeychainItemsToForms(&keychain_items); | |
496 } | |
497 | |
498 PasswordForm* MacKeychainPasswordFormAdapter::PasswordExactlyMatchingForm( | 606 PasswordForm* MacKeychainPasswordFormAdapter::PasswordExactlyMatchingForm( |
499 const PasswordForm& query_form) { | 607 const PasswordForm& query_form) { |
500 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); | 608 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); |
501 if (keychain_item) { | 609 if (keychain_item) { |
502 PasswordForm* form = new PasswordForm(); | 610 PasswordForm* form = new PasswordForm(); |
503 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 611 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
504 keychain_item, | 612 keychain_item, |
505 form); | 613 form, |
614 true); | |
506 keychain_->Free(keychain_item); | 615 keychain_->Free(keychain_item); |
507 return form; | 616 return form; |
508 } | 617 } |
509 return NULL; | 618 return NULL; |
510 } | 619 } |
511 | 620 |
512 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( | 621 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( |
513 const PasswordForm& query_form) { | 622 const PasswordForm& query_form) { |
514 std::string username = UTF16ToUTF8(query_form.username_value); | 623 std::string username = UTF16ToUTF8(query_form.username_value); |
515 std::vector<SecKeychainItemRef> matches = | 624 std::vector<SecKeychainItemRef> matches = |
516 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, | 625 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, |
517 NULL, username.c_str()); | 626 NULL, username.c_str()); |
518 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin(); | 627 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin(); |
519 i != matches.end(); ++i) { | 628 i != matches.end(); ++i) { |
520 keychain_->Free(*i); | 629 keychain_->Free(*i); |
521 } | 630 } |
522 | 631 |
523 return !matches.empty(); | 632 return !matches.empty(); |
524 } | 633 } |
525 | 634 |
526 std::vector<PasswordForm*> | 635 std::vector<SecKeychainItemRef> |
527 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { | 636 MacKeychainPasswordFormAdapter::GetAllPasswordFormKeychainItems() { |
528 SecAuthenticationType supported_auth_types[] = { | 637 SecAuthenticationType supported_auth_types[] = { |
529 kSecAuthenticationTypeHTMLForm, | 638 kSecAuthenticationTypeHTMLForm, |
530 kSecAuthenticationTypeHTTPBasic, | 639 kSecAuthenticationTypeHTTPBasic, |
531 kSecAuthenticationTypeHTTPDigest, | 640 kSecAuthenticationTypeHTTPDigest, |
532 }; | 641 }; |
533 | 642 |
534 std::vector<SecKeychainItemRef> matches; | 643 std::vector<SecKeychainItemRef> matches; |
535 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) { | 644 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) { |
536 KeychainSearch keychain_search(*keychain_); | 645 KeychainSearch keychain_search(*keychain_); |
537 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i], | 646 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i], |
538 NULL, NULL, NULL, CreatorCodeForSearch()); | 647 NULL, NULL, NULL, CreatorCodeForSearch()); |
539 keychain_search.FindMatchingItems(&matches); | 648 keychain_search.FindMatchingItems(&matches); |
540 } | 649 } |
650 return matches; | |
651 } | |
541 | 652 |
542 return ConvertKeychainItemsToForms(&matches); | 653 std::vector<PasswordForm*> |
654 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { | |
655 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); | |
656 return ConvertKeychainItemsToForms(&items); | |
543 } | 657 } |
544 | 658 |
545 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { | 659 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { |
546 // We should never be trying to store a blacklist in the keychain. | 660 // We should never be trying to store a blacklist in the keychain. |
547 DCHECK(!form.blacklisted_by_user); | 661 DCHECK(!form.blacklisted_by_user); |
548 | 662 |
549 std::string server; | 663 std::string server; |
550 std::string security_domain; | 664 std::string security_domain; |
551 int port; | 665 int port; |
552 bool is_secure; | 666 bool is_secure; |
553 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port, | 667 if (!internal_keychain_helpers::ExtractSignonRealmComponents( |
554 &is_secure, &security_domain)) { | 668 form.signon_realm, &server, &port, &is_secure, &security_domain)) { |
555 return false; | 669 return false; |
556 } | 670 } |
557 std::string username = UTF16ToUTF8(form.username_value); | 671 std::string username = UTF16ToUTF8(form.username_value); |
558 std::string password = UTF16ToUTF8(form.password_value); | 672 std::string password = UTF16ToUTF8(form.password_value); |
559 std::string path = form.origin.path(); | 673 std::string path = form.origin.path(); |
560 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 674 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
561 : kSecProtocolTypeHTTP; | 675 : kSecProtocolTypeHTTP; |
562 SecKeychainItemRef new_item = NULL; | 676 SecKeychainItemRef new_item = NULL; |
563 OSStatus result = keychain_->AddInternetPassword( | 677 OSStatus result = keychain_->AddInternetPassword( |
564 NULL, server.size(), server.c_str(), | 678 NULL, server.size(), server.c_str(), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
600 finds_only_owned_ = finds_only_owned; | 714 finds_only_owned_ = finds_only_owned; |
601 } | 715 } |
602 | 716 |
603 std::vector<PasswordForm*> | 717 std::vector<PasswordForm*> |
604 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( | 718 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( |
605 std::vector<SecKeychainItemRef>* items) { | 719 std::vector<SecKeychainItemRef>* items) { |
606 std::vector<PasswordForm*> keychain_forms; | 720 std::vector<PasswordForm*> keychain_forms; |
607 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); | 721 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); |
608 i != items->end(); ++i) { | 722 i != items->end(); ++i) { |
609 PasswordForm* form = new PasswordForm(); | 723 PasswordForm* form = new PasswordForm(); |
610 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 724 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
611 *i, form)) { | 725 *keychain_, *i, form, true)) { |
612 keychain_forms.push_back(form); | 726 keychain_forms.push_back(form); |
613 } | 727 } |
614 keychain_->Free(*i); | 728 keychain_->Free(*i); |
615 } | 729 } |
616 items->clear(); | 730 items->clear(); |
617 return keychain_forms; | 731 return keychain_forms; |
618 } | 732 } |
619 | 733 |
620 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( | 734 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( |
621 const PasswordForm& form) { | 735 const PasswordForm& form) { |
(...skipping 23 matching lines...) Expand all Loading... | |
645 MacKeychainPasswordFormAdapter::MatchingKeychainItems( | 759 MacKeychainPasswordFormAdapter::MatchingKeychainItems( |
646 const std::string& signon_realm, | 760 const std::string& signon_realm, |
647 autofill::PasswordForm::Scheme scheme, | 761 autofill::PasswordForm::Scheme scheme, |
648 const char* path, const char* username) { | 762 const char* path, const char* username) { |
649 std::vector<SecKeychainItemRef> matches; | 763 std::vector<SecKeychainItemRef> matches; |
650 | 764 |
651 std::string server; | 765 std::string server; |
652 std::string security_domain; | 766 std::string security_domain; |
653 int port; | 767 int port; |
654 bool is_secure; | 768 bool is_secure; |
655 if (!ExtractSignonRealmComponents(signon_realm, &server, &port, | 769 if (!internal_keychain_helpers::ExtractSignonRealmComponents( |
656 &is_secure, &security_domain)) { | 770 signon_realm, &server, &port, &is_secure, &security_domain)) { |
657 // TODO(stuartmorgan): Proxies will currently fail here, since their | 771 // TODO(stuartmorgan): Proxies will currently fail here, since their |
658 // signon_realm is not a URL. We need to detect the proxy case and handle | 772 // signon_realm is not a URL. We need to detect the proxy case and handle |
659 // it specially. | 773 // it specially. |
660 return matches; | 774 return matches; |
661 } | 775 } |
662 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 776 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
663 : kSecProtocolTypeHTTP; | 777 : kSecProtocolTypeHTTP; |
664 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); | 778 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); |
665 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? | 779 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? |
666 NULL : security_domain.c_str(); | 780 NULL : security_domain.c_str(); |
667 KeychainSearch keychain_search(*keychain_); | 781 KeychainSearch keychain_search(*keychain_); |
668 keychain_search.Init(server.c_str(), port, protocol, auth_type, | 782 keychain_search.Init(server.c_str(), port, protocol, auth_type, |
669 auth_domain, path, username, CreatorCodeForSearch()); | 783 auth_domain, path, username, CreatorCodeForSearch()); |
670 keychain_search.FindMatchingItems(&matches); | 784 keychain_search.FindMatchingItems(&matches); |
671 return matches; | 785 return matches; |
672 } | 786 } |
673 | 787 |
674 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | |
675 bool MacKeychainPasswordFormAdapter::ExtractSignonRealmComponents( | |
676 const std::string& signon_realm, std::string* server, int* port, | |
677 bool* is_secure, std::string* security_domain) { | |
678 // The signon_realm will be the Origin portion of a URL for an HTML form, | |
679 // and the same but with the security domain as a path for HTTP auth. | |
680 GURL realm_as_url(signon_realm); | |
681 if (!realm_as_url.is_valid()) { | |
682 return false; | |
683 } | |
684 | |
685 if (server) | |
686 *server = realm_as_url.host(); | |
687 if (is_secure) | |
688 *is_secure = realm_as_url.SchemeIsSecure(); | |
689 if (port) | |
690 *port = realm_as_url.has_port() ? atoi(realm_as_url.port().c_str()) : 0; | |
691 if (security_domain) { | |
692 // Strip the leading '/' off of the path to get the security domain. | |
693 if (realm_as_url.path().length() > 0) | |
694 *security_domain = realm_as_url.path().substr(1); | |
695 else | |
696 security_domain->clear(); | |
697 } | |
698 return true; | |
699 } | |
700 | |
701 // Returns the Keychain SecAuthenticationType type corresponding to |scheme|. | 788 // Returns the Keychain SecAuthenticationType type corresponding to |scheme|. |
702 SecAuthenticationType MacKeychainPasswordFormAdapter::AuthTypeForScheme( | 789 SecAuthenticationType MacKeychainPasswordFormAdapter::AuthTypeForScheme( |
703 PasswordForm::Scheme scheme) { | 790 PasswordForm::Scheme scheme) { |
704 switch (scheme) { | 791 switch (scheme) { |
705 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm; | 792 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm; |
706 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic; | 793 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic; |
707 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest; | 794 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest; |
708 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; | 795 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; |
709 } | 796 } |
710 NOTREACHED(); | 797 NOTREACHED(); |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1019 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 1106 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
1020 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); | 1107 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); |
1021 i != forms.end(); ++i) { | 1108 i != forms.end(); ++i) { |
1022 owned_keychain_adapter.RemovePassword(**i); | 1109 owned_keychain_adapter.RemovePassword(**i); |
1023 } | 1110 } |
1024 } | 1111 } |
1025 | 1112 |
1026 void PasswordStoreMac::CreateNotificationService() { | 1113 void PasswordStoreMac::CreateNotificationService() { |
1027 notification_service_.reset(content::NotificationService::Create()); | 1114 notification_service_.reset(content::NotificationService::Create()); |
1028 } | 1115 } |
OLD | NEW |