Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: chrome/browser/password_manager/password_store_mac.cc

Issue 147044: Wire up a LoginDatabase for PasswordStoreMac (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/password_manager/password_store_mac.h ('k') | chrome/browser/profile.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/string_util.h" 14 #include "base/string_util.h"
14 #include "base/time.h" 15 #include "base/time.h"
15 #include "chrome/browser/keychain_mac.h" 16 #include "chrome/browser/keychain_mac.h"
17 #include "chrome/browser/password_manager/login_database_mac.h"
16 18
17 using webkit_glue::PasswordForm; 19 using webkit_glue::PasswordForm;
18 20
19 namespace internal_keychain_helpers { 21 namespace internal_keychain_helpers {
20 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);
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 // on each of them when it is finished with them. 246 // on each of them when it is finished with them.
245 void FindMatchingKeychainItems(const MacKeychain& keychain, 247 void FindMatchingKeychainItems(const MacKeychain& keychain,
246 const std::string& signon_realm, 248 const std::string& signon_realm,
247 PasswordForm::Scheme scheme, 249 PasswordForm::Scheme scheme,
248 std::vector<SecKeychainItemRef>* items) { 250 std::vector<SecKeychainItemRef>* items) {
249 // Construct a keychain search based on the signon_realm and scheme. 251 // Construct a keychain search based on the signon_realm and scheme.
250 std::string server; 252 std::string server;
251 std::string security_domain; 253 std::string security_domain;
252 int port; 254 int port;
253 bool is_secure; 255 bool is_secure;
254 if (!internal_keychain_helpers::ExtractSignonRealmComponents( 256 if (!ExtractSignonRealmComponents(signon_realm, &server, &port, &is_secure,
255 signon_realm, &server, &port, &is_secure, &security_domain)) { 257 &security_domain)) {
256 // TODO(stuartmorgan): Proxies will currently fail here, since their 258 // TODO(stuartmorgan): Proxies will currently fail here, since their
257 // signon_realm is not a URL. We need to detect the proxy case and handle 259 // signon_realm is not a URL. We need to detect the proxy case and handle
258 // it specially. 260 // it specially.
259 return; 261 return;
260 } 262 }
261 263
262 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS 264 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS
263 : kSecProtocolTypeHTTP; 265 : kSecProtocolTypeHTTP;
264 SecAuthenticationType auth_type = 266 SecAuthenticationType auth_type = AuthTypeForScheme(scheme);
265 internal_keychain_helpers::AuthTypeForScheme(scheme);
266 267
267 internal_keychain_helpers::KeychainSearch keychain_search(keychain); 268 KeychainSearch keychain_search(keychain);
268 keychain_search.Init(server.c_str(), port, protocol, auth_type, 269 keychain_search.Init(server.c_str(), port, protocol, auth_type,
269 (scheme == PasswordForm::SCHEME_HTML) ? 270 (scheme == PasswordForm::SCHEME_HTML) ?
270 NULL : security_domain.c_str(), 271 NULL : security_domain.c_str(),
271 NULL, NULL); 272 NULL, NULL);
272 keychain_search.FindMatchingItems(items); 273 keychain_search.FindMatchingItems(items);
273 } 274 }
274 275
275 SecKeychainItemRef FindMatchingKeychainItem(const MacKeychain& keychain, 276 SecKeychainItemRef FindMatchingKeychainItem(const MacKeychain& keychain,
276 const PasswordForm& form) { 277 const PasswordForm& form) {
277 // We don't store blacklist entries in the keychain, so the answer to "what 278 // We don't store blacklist entries in the keychain, so the answer to "what
278 // Keychain item goes with this form" is always "nothing" for blacklists. 279 // Keychain item goes with this form" is always "nothing" for blacklists.
279 if (form.blacklisted_by_user) { 280 if (form.blacklisted_by_user) {
280 return NULL; 281 return NULL;
281 } 282 }
282 283
283 // Construct a keychain search based on all the unique attributes. 284 // Construct a keychain search based on all the unique attributes.
284 std::string server; 285 std::string server;
285 std::string security_domain; 286 std::string security_domain;
286 int port; 287 int port;
287 bool is_secure; 288 bool is_secure;
288 if (!internal_keychain_helpers::ExtractSignonRealmComponents( 289 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port,
289 form.signon_realm, &server, &port, &is_secure, &security_domain)) { 290 &is_secure, &security_domain)) {
290 // TODO(stuartmorgan): Proxies will currently fail here, since their 291 // TODO(stuartmorgan): Proxies will currently fail here, since their
291 // signon_realm is not a URL. We need to detect the proxy case and handle 292 // signon_realm is not a URL. We need to detect the proxy case and handle
292 // it specially. 293 // it specially.
293 return NULL; 294 return NULL;
294 } 295 }
295 296
296 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS 297 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS
297 : kSecProtocolTypeHTTP; 298 : kSecProtocolTypeHTTP;
298 SecAuthenticationType auth_type = 299 SecAuthenticationType auth_type = AuthTypeForScheme(form.scheme);
299 internal_keychain_helpers::AuthTypeForScheme(form.scheme);
300 std::string path = form.origin.path(); 300 std::string path = form.origin.path();
301 std::string username = WideToUTF8(form.username_value); 301 std::string username = WideToUTF8(form.username_value);
302 302
303 internal_keychain_helpers::KeychainSearch keychain_search(keychain); 303 KeychainSearch keychain_search(keychain);
304 keychain_search.Init(server.c_str(), port, protocol, auth_type, 304 keychain_search.Init(server.c_str(), port, protocol, auth_type,
305 (form.scheme == PasswordForm::SCHEME_HTML) ? 305 (form.scheme == PasswordForm::SCHEME_HTML) ?
306 NULL : security_domain.c_str(), 306 NULL : security_domain.c_str(),
307 path.c_str(), username.c_str()); 307 path.c_str(), username.c_str());
308 308
309 std::vector<SecKeychainItemRef> matches; 309 std::vector<SecKeychainItemRef> matches;
310 keychain_search.FindMatchingItems(&matches); 310 keychain_search.FindMatchingItems(&matches);
311 311
312 if (matches.size() == 0) { 312 if (matches.size() == 0) {
313 return NULL; 313 return NULL;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 { 386 {
387 SecProtocolType protocol = *(static_cast<SecProtocolType*>(attr.data)); 387 SecProtocolType protocol = *(static_cast<SecProtocolType*>(attr.data));
388 // TODO(stuartmorgan): Handle proxy types 388 // TODO(stuartmorgan): Handle proxy types
389 form->ssl_valid = (protocol == kSecProtocolTypeHTTPS); 389 form->ssl_valid = (protocol == kSecProtocolTypeHTTPS);
390 break; 390 break;
391 } 391 }
392 case kSecAuthenticationTypeItemAttr: 392 case kSecAuthenticationTypeItemAttr:
393 { 393 {
394 SecAuthenticationType auth_type = 394 SecAuthenticationType auth_type =
395 *(static_cast<SecAuthenticationType*>(attr.data)); 395 *(static_cast<SecAuthenticationType*>(attr.data));
396 form->scheme = internal_keychain_helpers::SchemeForAuthType(auth_type); 396 form->scheme = SchemeForAuthType(auth_type);
397 break; 397 break;
398 } 398 }
399 case kSecSecurityDomainItemAttr: 399 case kSecSecurityDomainItemAttr:
400 security_domain.assign(static_cast<const char *>(attr.data), 400 security_domain.assign(static_cast<const char *>(attr.data),
401 attr.length); 401 attr.length);
402 break; 402 break;
403 case kSecCreationDateItemAttr: 403 case kSecCreationDateItemAttr:
404 // The only way to get a date out of Keychain is as a string. Really. 404 // The only way to get a date out of Keychain is as a string. Really.
405 // (The docs claim it's an int, but the header is correct.) 405 // (The docs claim it's an int, but the header is correct.)
406 internal_keychain_helpers::TimeFromKeychainTimeString( 406 TimeFromKeychainTimeString(static_cast<char*>(attr.data), attr.length,
407 static_cast<char*>(attr.data), attr.length, &form->date_created); 407 &form->date_created);
408 break; 408 break;
409 case kSecNegativeItemAttr: 409 case kSecNegativeItemAttr:
410 Boolean negative_item = *(static_cast<Boolean*>(attr.data)); 410 Boolean negative_item = *(static_cast<Boolean*>(attr.data));
411 if (negative_item) { 411 if (negative_item) {
412 form->blacklisted_by_user = true; 412 form->blacklisted_by_user = true;
413 } 413 }
414 break; 414 break;
415 } 415 }
416 } 416 }
417 keychain.ItemFreeAttributesAndData(attrList, password_data); 417 keychain.ItemFreeAttributesAndData(attrList, password_data);
418 418
419 // kSecNegativeItemAttr doesn't seem to actually be in widespread use. In 419 // kSecNegativeItemAttr doesn't seem to actually be in widespread use. In
420 // practice, other browsers seem to use a "" or " " password (and a special 420 // practice, other browsers seem to use a "" or " " password (and a special
421 // user name) to indicated blacklist entries. 421 // user name) to indicated blacklist entries.
422 if (form->password_value.empty() || form->password_value == L" ") { 422 if (form->password_value.empty() || form->password_value == L" ") {
423 form->blacklisted_by_user = true; 423 form->blacklisted_by_user = true;
424 } 424 }
425 425
426 form->origin = internal_keychain_helpers::URLFromComponents(form->ssl_valid, 426 form->origin = URLFromComponents(form->ssl_valid, server, port, path);
427 server, port,
428 path);
429 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm 427 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm
430 // format. 428 // format.
431 form->signon_realm = form->origin.GetOrigin().spec(); 429 form->signon_realm = form->origin.GetOrigin().spec();
432 if (form->scheme != PasswordForm::SCHEME_HTML) { 430 if (form->scheme != PasswordForm::SCHEME_HTML) {
433 form->signon_realm.append(security_domain); 431 form->signon_realm.append(security_domain);
434 } 432 }
435 return true; 433 return true;
436 } 434 }
437 435
438 bool AddKeychainEntryForForm(const MacKeychain& keychain, 436 bool AddKeychainEntryForForm(const MacKeychain& keychain,
439 const PasswordForm& form) { 437 const PasswordForm& form) {
440 std::string server; 438 std::string server;
441 std::string security_domain; 439 std::string security_domain;
442 int port; 440 int port;
443 bool is_secure; 441 bool is_secure;
444 if (!internal_keychain_helpers::ExtractSignonRealmComponents( 442 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port,
445 form.signon_realm, &server, &port, &is_secure, &security_domain)) { 443 &is_secure, &security_domain)) {
446 return false; 444 return false;
447 } 445 }
448 std::string username = WideToUTF8(form.username_value); 446 std::string username = WideToUTF8(form.username_value);
449 std::string password = WideToUTF8(form.password_value); 447 std::string password = WideToUTF8(form.password_value);
450 std::string path = form.origin.path(); 448 std::string path = form.origin.path();
451 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS 449 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS
452 : kSecProtocolTypeHTTP; 450 : kSecProtocolTypeHTTP;
453 OSStatus result = keychain.AddInternetPassword( 451 OSStatus result = keychain.AddInternetPassword(
454 NULL, server.size(), server.c_str(), 452 NULL, server.size(), server.c_str(),
455 security_domain.size(), security_domain.c_str(), 453 security_domain.size(), security_domain.c_str(),
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 } else { 555 } else {
558 if (used_keychain_forms.find(keychain_form) == used_keychain_forms.end()) 556 if (used_keychain_forms.find(keychain_form) == used_keychain_forms.end())
559 merged_forms->push_back(keychain_form); 557 merged_forms->push_back(keychain_form);
560 else 558 else
561 delete keychain_form; 559 delete keychain_form;
562 i = keychain_forms->erase(i); 560 i = keychain_forms->erase(i);
563 } 561 }
564 } 562 }
565 } 563 }
566 564
567 } // internal_keychain_helpers 565 // Returns PasswordForms constructed from the given Keychain items.
566 // Caller is responsible for deleting the returned forms.
567 std::vector<PasswordForm*> CreateFormsFromKeychainItems(
568 const MacKeychain& keychain,
569 const std::vector<SecKeychainItemRef>& items) {
570 std::vector<PasswordForm*> keychain_forms;
571 for (std::vector<SecKeychainItemRef>::const_iterator i = items.begin();
572 i != items.end(); ++i) {
573 PasswordForm* form = new PasswordForm();
574 if (FillPasswordFormFromKeychainItem(keychain, *i, form)) {
575 keychain_forms.push_back(form);
576 }
577 }
578 return keychain_forms;
579 }
580
581 // Returns PasswordForms for each keychain entry matching |form|.
582 // Caller is responsible for deleting the returned forms.
583 std::vector<PasswordForm*> KeychainFormsMatchingForm(
584 const MacKeychain& keychain, const PasswordForm& query_form) {
585 std::vector<SecKeychainItemRef> keychain_items;
586 FindMatchingKeychainItems(keychain, query_form.signon_realm,
587 query_form.scheme, &keychain_items);
588
589 std::vector<PasswordForm*> keychain_forms =
590 CreateFormsFromKeychainItems(keychain, keychain_items);
591 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin();
592 i != keychain_items.end(); ++i) {
593 keychain.Free(*i);
594 }
595 return keychain_forms;
596 }
597
598 } // namespace internal_keychain_helpers
568 599
569 #pragma mark - 600 #pragma mark -
570 601
571 PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain) 602 PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain,
572 : keychain_(keychain) { 603 LoginDatabaseMac* login_db)
604 : keychain_(keychain), login_metadata_db_(login_db) {
573 DCHECK(keychain_.get()); 605 DCHECK(keychain_.get());
606 DCHECK(login_metadata_db_.get());
574 } 607 }
575 608
609 PasswordStoreMac::~PasswordStoreMac() {}
610
576 void PasswordStoreMac::AddLoginImpl(const PasswordForm& form) { 611 void PasswordStoreMac::AddLoginImpl(const PasswordForm& form) {
577 NOTIMPLEMENTED(); 612 NOTIMPLEMENTED();
578 } 613 }
579 614
580 void PasswordStoreMac::UpdateLoginImpl(const PasswordForm& form) { 615 void PasswordStoreMac::UpdateLoginImpl(const PasswordForm& form) {
581 NOTIMPLEMENTED(); 616 NOTIMPLEMENTED();
582 } 617 }
583 618
584 void PasswordStoreMac::RemoveLoginImpl(const PasswordForm& form) { 619 void PasswordStoreMac::RemoveLoginImpl(const PasswordForm& form) {
585 NOTIMPLEMENTED(); 620 NOTIMPLEMENTED();
586 } 621 }
587 622
588 void PasswordStoreMac::GetLoginsImpl(GetLoginsRequest* request) { 623 void PasswordStoreMac::GetLoginsImpl(GetLoginsRequest* request) {
589 std::vector<SecKeychainItemRef> keychain_items; 624 std::vector<PasswordForm*> keychain_forms =
625 internal_keychain_helpers::KeychainFormsMatchingForm(*keychain_,
626 request->form);
590 627
591 internal_keychain_helpers::FindMatchingKeychainItems( 628 std::vector<PasswordForm*> database_forms;
592 *keychain_, request->form.signon_realm, request->form.scheme, 629 login_metadata_db_->GetLogins(request->form, &database_forms);
593 &keychain_items);
594 630
595 std::vector<PasswordForm*> forms; 631 std::vector<PasswordForm*> merged_forms;
632 internal_keychain_helpers::MergePasswordForms(&keychain_forms,
633 &database_forms,
634 &merged_forms);
596 635
597 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin(); 636 // Clean up any orphaned database entries.
598 i != keychain_items.end(); ++i) { 637 for (std::vector<PasswordForm*>::iterator i = database_forms.begin();
599 // Consumer is responsible for deleting the forms when they are done... 638 i != database_forms.end(); ++i) {
600 PasswordForm* form = new PasswordForm(); 639 login_metadata_db_->RemoveLogin(**i);
601 SecKeychainItemRef keychain_item = *i;
602 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(
603 *keychain_, keychain_item, form)) {
604 forms.push_back(form);
605 }
606 // ... but we need to clean up the keychain item.
607 keychain_->Free(keychain_item);
608 } 640 }
641 // Delete the forms we aren't returning.
642 STLDeleteElements(&database_forms);
643 STLDeleteElements(&keychain_forms);
609 644
610 NotifyConsumer(request, forms); 645 NotifyConsumer(request, merged_forms);
611 } 646 }
OLDNEW
« no previous file with comments | « chrome/browser/password_manager/password_store_mac.h ('k') | chrome/browser/profile.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698