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); |
| 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 scoped_ptr<PasswordForm> form_with_password(new PasswordForm()); |
| 572 internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
| 573 keychain, |
| 574 *(i->first), |
| 575 form_with_password.get(), |
| 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 matches.push_back(form_with_password.release()); |
| 580 } |
| 581 } |
| 582 return matches; |
| 583 } |
| 584 |
468 } // namespace internal_keychain_helpers | 585 } // namespace internal_keychain_helpers |
469 | 586 |
470 #pragma mark - | 587 #pragma mark - |
471 | 588 |
472 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( | 589 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( |
473 const AppleKeychain* keychain) | 590 const AppleKeychain* keychain) |
474 : keychain_(keychain), finds_only_owned_(false) { | 591 : keychain_(keychain), finds_only_owned_(false) { |
475 } | 592 } |
476 | 593 |
477 std::vector<PasswordForm*> | 594 std::vector<PasswordForm*> |
478 MacKeychainPasswordFormAdapter::PasswordsFillingForm( | 595 MacKeychainPasswordFormAdapter::PasswordsFillingForm( |
479 const PasswordForm& query_form) { | 596 const PasswordForm& query_form) { |
480 std::vector<SecKeychainItemRef> keychain_items = | 597 std::vector<SecKeychainItemRef> keychain_items = |
481 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, | 598 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, |
482 NULL, NULL); | 599 NULL, NULL); |
483 | 600 |
484 return ConvertKeychainItemsToForms(&keychain_items); | 601 return ConvertKeychainItemsToForms(&keychain_items); |
485 } | 602 } |
486 | 603 |
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( | 604 PasswordForm* MacKeychainPasswordFormAdapter::PasswordExactlyMatchingForm( |
499 const PasswordForm& query_form) { | 605 const PasswordForm& query_form) { |
500 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); | 606 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); |
501 if (keychain_item) { | 607 if (keychain_item) { |
502 PasswordForm* form = new PasswordForm(); | 608 PasswordForm* form = new PasswordForm(); |
503 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 609 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
504 keychain_item, | 610 keychain_item, |
505 form); | 611 form, |
| 612 true); |
506 keychain_->Free(keychain_item); | 613 keychain_->Free(keychain_item); |
507 return form; | 614 return form; |
508 } | 615 } |
509 return NULL; | 616 return NULL; |
510 } | 617 } |
511 | 618 |
512 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( | 619 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( |
513 const PasswordForm& query_form) { | 620 const PasswordForm& query_form) { |
514 std::string username = UTF16ToUTF8(query_form.username_value); | 621 std::string username = UTF16ToUTF8(query_form.username_value); |
515 std::vector<SecKeychainItemRef> matches = | 622 std::vector<SecKeychainItemRef> matches = |
516 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, | 623 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, |
517 NULL, username.c_str()); | 624 NULL, username.c_str()); |
518 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin(); | 625 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin(); |
519 i != matches.end(); ++i) { | 626 i != matches.end(); ++i) { |
520 keychain_->Free(*i); | 627 keychain_->Free(*i); |
521 } | 628 } |
522 | 629 |
523 return !matches.empty(); | 630 return !matches.empty(); |
524 } | 631 } |
525 | 632 |
526 std::vector<PasswordForm*> | 633 std::vector<SecKeychainItemRef> |
527 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { | 634 MacKeychainPasswordFormAdapter::GetAllPasswordFormKeychainItems() { |
528 SecAuthenticationType supported_auth_types[] = { | 635 SecAuthenticationType supported_auth_types[] = { |
529 kSecAuthenticationTypeHTMLForm, | 636 kSecAuthenticationTypeHTMLForm, |
530 kSecAuthenticationTypeHTTPBasic, | 637 kSecAuthenticationTypeHTTPBasic, |
531 kSecAuthenticationTypeHTTPDigest, | 638 kSecAuthenticationTypeHTTPDigest, |
532 }; | 639 }; |
533 | 640 |
534 std::vector<SecKeychainItemRef> matches; | 641 std::vector<SecKeychainItemRef> matches; |
535 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) { | 642 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) { |
536 KeychainSearch keychain_search(*keychain_); | 643 KeychainSearch keychain_search(*keychain_); |
537 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i], | 644 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i], |
538 NULL, NULL, NULL, CreatorCodeForSearch()); | 645 NULL, NULL, NULL, CreatorCodeForSearch()); |
539 keychain_search.FindMatchingItems(&matches); | 646 keychain_search.FindMatchingItems(&matches); |
540 } | 647 } |
| 648 return matches; |
| 649 } |
541 | 650 |
542 return ConvertKeychainItemsToForms(&matches); | 651 std::vector<PasswordForm*> |
| 652 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { |
| 653 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); |
| 654 return ConvertKeychainItemsToForms(&items); |
543 } | 655 } |
544 | 656 |
545 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { | 657 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { |
546 // We should never be trying to store a blacklist in the keychain. | 658 // We should never be trying to store a blacklist in the keychain. |
547 DCHECK(!form.blacklisted_by_user); | 659 DCHECK(!form.blacklisted_by_user); |
548 | 660 |
549 std::string server; | 661 std::string server; |
550 std::string security_domain; | 662 std::string security_domain; |
551 int port; | 663 int port; |
552 bool is_secure; | 664 bool is_secure; |
553 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port, | 665 if (!internal_keychain_helpers::ExtractSignonRealmComponents( |
554 &is_secure, &security_domain)) { | 666 form.signon_realm, &server, &port, &is_secure, &security_domain)) { |
555 return false; | 667 return false; |
556 } | 668 } |
557 std::string username = UTF16ToUTF8(form.username_value); | 669 std::string username = UTF16ToUTF8(form.username_value); |
558 std::string password = UTF16ToUTF8(form.password_value); | 670 std::string password = UTF16ToUTF8(form.password_value); |
559 std::string path = form.origin.path(); | 671 std::string path = form.origin.path(); |
560 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 672 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
561 : kSecProtocolTypeHTTP; | 673 : kSecProtocolTypeHTTP; |
562 SecKeychainItemRef new_item = NULL; | 674 SecKeychainItemRef new_item = NULL; |
563 OSStatus result = keychain_->AddInternetPassword( | 675 OSStatus result = keychain_->AddInternetPassword( |
564 NULL, server.size(), server.c_str(), | 676 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; | 712 finds_only_owned_ = finds_only_owned; |
601 } | 713 } |
602 | 714 |
603 std::vector<PasswordForm*> | 715 std::vector<PasswordForm*> |
604 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( | 716 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( |
605 std::vector<SecKeychainItemRef>* items) { | 717 std::vector<SecKeychainItemRef>* items) { |
606 std::vector<PasswordForm*> keychain_forms; | 718 std::vector<PasswordForm*> keychain_forms; |
607 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); | 719 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); |
608 i != items->end(); ++i) { | 720 i != items->end(); ++i) { |
609 PasswordForm* form = new PasswordForm(); | 721 PasswordForm* form = new PasswordForm(); |
610 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 722 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
611 *i, form)) { | 723 *keychain_, *i, form, true)) { |
612 keychain_forms.push_back(form); | 724 keychain_forms.push_back(form); |
613 } | 725 } |
614 keychain_->Free(*i); | 726 keychain_->Free(*i); |
615 } | 727 } |
616 items->clear(); | 728 items->clear(); |
617 return keychain_forms; | 729 return keychain_forms; |
618 } | 730 } |
619 | 731 |
620 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( | 732 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( |
621 const PasswordForm& form) { | 733 const PasswordForm& form) { |
(...skipping 23 matching lines...) Expand all Loading... |
645 MacKeychainPasswordFormAdapter::MatchingKeychainItems( | 757 MacKeychainPasswordFormAdapter::MatchingKeychainItems( |
646 const std::string& signon_realm, | 758 const std::string& signon_realm, |
647 autofill::PasswordForm::Scheme scheme, | 759 autofill::PasswordForm::Scheme scheme, |
648 const char* path, const char* username) { | 760 const char* path, const char* username) { |
649 std::vector<SecKeychainItemRef> matches; | 761 std::vector<SecKeychainItemRef> matches; |
650 | 762 |
651 std::string server; | 763 std::string server; |
652 std::string security_domain; | 764 std::string security_domain; |
653 int port; | 765 int port; |
654 bool is_secure; | 766 bool is_secure; |
655 if (!ExtractSignonRealmComponents(signon_realm, &server, &port, | 767 if (!internal_keychain_helpers::ExtractSignonRealmComponents( |
656 &is_secure, &security_domain)) { | 768 signon_realm, &server, &port, &is_secure, &security_domain)) { |
657 // TODO(stuartmorgan): Proxies will currently fail here, since their | 769 // 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 | 770 // signon_realm is not a URL. We need to detect the proxy case and handle |
659 // it specially. | 771 // it specially. |
660 return matches; | 772 return matches; |
661 } | 773 } |
662 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 774 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
663 : kSecProtocolTypeHTTP; | 775 : kSecProtocolTypeHTTP; |
664 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); | 776 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); |
665 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? | 777 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? |
666 NULL : security_domain.c_str(); | 778 NULL : security_domain.c_str(); |
667 KeychainSearch keychain_search(*keychain_); | 779 KeychainSearch keychain_search(*keychain_); |
668 keychain_search.Init(server.c_str(), port, protocol, auth_type, | 780 keychain_search.Init(server.c_str(), port, protocol, auth_type, |
669 auth_domain, path, username, CreatorCodeForSearch()); | 781 auth_domain, path, username, CreatorCodeForSearch()); |
670 keychain_search.FindMatchingItems(&matches); | 782 keychain_search.FindMatchingItems(&matches); |
671 return matches; | 783 return matches; |
672 } | 784 } |
673 | 785 |
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|. | 786 // Returns the Keychain SecAuthenticationType type corresponding to |scheme|. |
702 SecAuthenticationType MacKeychainPasswordFormAdapter::AuthTypeForScheme( | 787 SecAuthenticationType MacKeychainPasswordFormAdapter::AuthTypeForScheme( |
703 PasswordForm::Scheme scheme) { | 788 PasswordForm::Scheme scheme) { |
704 switch (scheme) { | 789 switch (scheme) { |
705 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm; | 790 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm; |
706 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic; | 791 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic; |
707 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest; | 792 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest; |
708 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; | 793 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; |
709 } | 794 } |
710 NOTREACHED(); | 795 NOTREACHED(); |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); | 1104 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
1020 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); | 1105 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); |
1021 i != forms.end(); ++i) { | 1106 i != forms.end(); ++i) { |
1022 owned_keychain_adapter.RemovePassword(**i); | 1107 owned_keychain_adapter.RemovePassword(**i); |
1023 } | 1108 } |
1024 } | 1109 } |
1025 | 1110 |
1026 void PasswordStoreMac::CreateNotificationService() { | 1111 void PasswordStoreMac::CreateNotificationService() { |
1027 notification_service_.reset(content::NotificationService::Create()); | 1112 notification_service_.reset(content::NotificationService::Create()); |
1028 } | 1113 } |
OLD | NEW |