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 "testing/gtest/include/gtest/gtest.h" | 5 #include "testing/gtest/include/gtest/gtest.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/stl_util-inl.h" |
8 #include "chrome/browser/keychain_mock_mac.h" | 9 #include "chrome/browser/keychain_mock_mac.h" |
9 #include "chrome/browser/password_manager/password_store_mac.h" | 10 #include "chrome/browser/password_manager/password_store_mac.h" |
10 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 11 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
11 | 12 |
12 using webkit_glue::PasswordForm; | 13 using webkit_glue::PasswordForm; |
13 | 14 |
14 class PasswordStoreMacTest : public testing::Test { | 15 class PasswordStoreMacTest : public testing::Test { |
15 public: | 16 public: |
16 virtual void SetUp() { | 17 virtual void SetUp() { |
17 MockKeychain::KeychainTestData test_data[] = { | 18 MockKeychain::KeychainTestData test_data[] = { |
(...skipping 23 matching lines...) Expand all Loading... |
41 "Password Not Stored", " ", false }, | 42 "Password Not Stored", " ", false }, |
42 // HTTP auth basic, with port and path. | 43 // HTTP auth basic, with port and path. |
43 { kSecAuthenticationTypeHTTPBasic, "some.domain.com", | 44 { kSecAuthenticationTypeHTTPBasic, "some.domain.com", |
44 kSecProtocolTypeHTTP, "/insecure.html", 4567, "low_security", | 45 kSecProtocolTypeHTTP, "/insecure.html", 4567, "low_security", |
45 "19980330100000Z", | 46 "19980330100000Z", |
46 "basic_auth_user", "basic", false }, | 47 "basic_auth_user", "basic", false }, |
47 // HTTP auth digest, secure. | 48 // HTTP auth digest, secure. |
48 { kSecAuthenticationTypeHTTPDigest, "some.domain.com", | 49 { kSecAuthenticationTypeHTTPDigest, "some.domain.com", |
49 kSecProtocolTypeHTTPS, NULL, 0, "high_security", "19980330100000Z", | 50 kSecProtocolTypeHTTPS, NULL, 0, "high_security", "19980330100000Z", |
50 "digest_auth_user", "digest", false }, | 51 "digest_auth_user", "digest", false }, |
| 52 // An FTP password with an invalid date, for edge-case testing. |
| 53 { kSecAuthenticationTypeDefault, "a.server.com", |
| 54 kSecProtocolTypeFTP, NULL, 0, NULL, "20010203040", |
| 55 "abc", "123", false }, |
51 }; | 56 }; |
52 | 57 |
53 // Save one slot for use by AddInternetPassword. | 58 // Save one slot for use by AddInternetPassword. |
54 unsigned int capacity = arraysize(test_data) + 1; | 59 unsigned int capacity = arraysize(test_data) + 1; |
55 keychain_ = new MockKeychain(capacity); | 60 keychain_ = new MockKeychain(capacity); |
56 | 61 |
57 for (unsigned int i = 0; i < arraysize(test_data); ++i) { | 62 for (unsigned int i = 0; i < arraysize(test_data); ++i) { |
58 keychain_->AddTestItem(test_data[i]); | 63 keychain_->AddTestItem(test_data[i]); |
59 } | 64 } |
60 } | 65 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } else { | 175 } else { |
171 EXPECT_TRUE(form->blacklisted_by_user) << test_label; | 176 EXPECT_TRUE(form->blacklisted_by_user) << test_label; |
172 } | 177 } |
173 EXPECT_EQ(expectation->preferred, form->preferred) << test_label; | 178 EXPECT_EQ(expectation->preferred, form->preferred) << test_label; |
174 EXPECT_EQ(expectation->ssl_valid, form->ssl_valid) << test_label; | 179 EXPECT_EQ(expectation->ssl_valid, form->ssl_valid) << test_label; |
175 EXPECT_DOUBLE_EQ(expectation->creation_time, | 180 EXPECT_DOUBLE_EQ(expectation->creation_time, |
176 form->date_created.ToDoubleT()) << test_label; | 181 form->date_created.ToDoubleT()) << test_label; |
177 } | 182 } |
178 } | 183 } |
179 | 184 |
180 // Frees all the Keychain items in |items|, and clears the vector. | |
181 static void FreeKeychainItems(const MacKeychain& keychain, | |
182 std::vector<SecKeychainItemRef>* items) { | |
183 CHECK(items); | |
184 for (std::vector<SecKeychainItemRef>::iterator i = items->begin(); | |
185 i != items->end(); ++i) { | |
186 keychain.Free(*i); | |
187 } | |
188 items->clear(); | |
189 } | |
190 | |
191 // Deletes all the PasswordForms in |forms|, and clears the vector. | |
192 static void DeletePasswordForms(std::vector<PasswordForm*>* forms) { | |
193 CHECK(forms); | |
194 for (std::vector<PasswordForm*>::iterator i = forms->begin(); | |
195 i != forms->end(); ++i) { | |
196 delete *i; | |
197 } | |
198 forms->clear(); | |
199 } | |
200 | |
201 #pragma mark - | 185 #pragma mark - |
202 | 186 |
203 TEST_F(PasswordStoreMacTest, TestSignonRealmParsing) { | |
204 typedef struct { | |
205 const char* signon_realm; | |
206 const bool expected_parsed; | |
207 const char* expected_server; | |
208 const bool expected_is_secure; | |
209 const int expected_port; | |
210 const char* expected_security_domain; | |
211 } TestData; | |
212 | |
213 TestData test_data[] = { | |
214 // HTML form signon realms. | |
215 { "http://www.domain.com/", | |
216 true, "www.domain.com", false, 0, "" }, | |
217 { "https://foo.org:9999/", | |
218 true, "foo.org", true, 9999, "" }, | |
219 // HTTP auth signon realms. | |
220 { "http://httpauth.com:8080/lowsecurity", | |
221 true, "httpauth.com", false, 8080, "lowsecurity" }, | |
222 { "https://httpauth.com/highsecurity", | |
223 true, "httpauth.com", true, 0 , "highsecurity" }, | |
224 // Bogus realms | |
225 { "blahblahblah", | |
226 false, false, "", 0, "" }, | |
227 { "foo/bar/baz", | |
228 false, false, "", 0, "" }, | |
229 }; | |
230 | |
231 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | |
232 std::string server; | |
233 std::string security_domain; | |
234 bool is_secure = false; | |
235 int port = -1; | |
236 bool parsed = internal_keychain_helpers::ExtractSignonRealmComponents( | |
237 std::string(test_data[i].signon_realm), &server, &port, &is_secure, | |
238 &security_domain); | |
239 EXPECT_EQ(test_data[i].expected_parsed, parsed) << "In iteration " << i; | |
240 | |
241 if (!parsed) { | |
242 continue; // If parse failed, out params are undefined. | |
243 } | |
244 EXPECT_EQ(std::string(test_data[i].expected_server), server) | |
245 << "In iteration " << i; | |
246 EXPECT_EQ(std::string(test_data[i].expected_security_domain), | |
247 security_domain) | |
248 << "In iteration " << i; | |
249 EXPECT_EQ(test_data[i].expected_is_secure, is_secure) | |
250 << "In iteration " << i; | |
251 EXPECT_EQ(test_data[i].expected_port, port) << "In iteration " << i; | |
252 } | |
253 | |
254 // NULLs are allowed for out params. | |
255 bool parsed = internal_keychain_helpers::ExtractSignonRealmComponents( | |
256 std::string("http://foo.bar.com:1234/baz"), NULL, NULL, NULL, NULL); | |
257 EXPECT_TRUE(parsed); | |
258 } | |
259 | |
260 TEST_F(PasswordStoreMacTest, TestURLConstruction) { | |
261 std::string host("exampledomain.com"); | |
262 std::string path("/path/to/page.html"); | |
263 | |
264 GURL full_url = internal_keychain_helpers::URLFromComponents(false, host, | |
265 1234, path); | |
266 EXPECT_TRUE(full_url.is_valid()); | |
267 EXPECT_EQ(GURL("http://exampledomain.com:1234/path/to/page.html"), full_url); | |
268 | |
269 GURL simple_secure_url = internal_keychain_helpers::URLFromComponents( | |
270 true, host, 0, std::string("")); | |
271 EXPECT_TRUE(simple_secure_url.is_valid()); | |
272 EXPECT_EQ(GURL("https://exampledomain.com/"), simple_secure_url); | |
273 } | |
274 | |
275 TEST_F(PasswordStoreMacTest, TestKeychainTime) { | |
276 typedef struct { | |
277 const char* time_string; | |
278 const bool expected_parsed; | |
279 const int expected_year; | |
280 const int expected_month; | |
281 const int expected_day; | |
282 const int expected_hour; | |
283 const int expected_minute; | |
284 const int expected_second; | |
285 } TestData; | |
286 | |
287 TestData test_data[] = { | |
288 // HTML form signon realms. | |
289 { "19980330100000Z", true, 1998, 3, 30, 10, 0, 0 }, | |
290 { "19991231235959Z", true, 1999, 12, 31, 23, 59, 59 }, | |
291 { "20000101000000Z", true, 2000, 1, 1, 0, 0, 0 }, | |
292 { "20011112012843Z", true, 2001, 11, 12, 1, 28, 43 }, | |
293 { "20020601171530Z", true, 2002, 6, 1, 17, 15, 30 }, | |
294 { "20100908070605Z", true, 2010, 9, 8, 7, 6, 5 }, | |
295 { "20010203040", false, 0, 0, 0, 0, 0, 0 }, | |
296 }; | |
297 | |
298 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | |
299 base::Time time; | |
300 bool parsed = internal_keychain_helpers::TimeFromKeychainTimeString( | |
301 test_data[i].time_string, strlen(test_data[i].time_string), &time); | |
302 EXPECT_EQ(test_data[i].expected_parsed, parsed) << "In iteration " << i; | |
303 if (!parsed) { | |
304 continue; | |
305 } | |
306 | |
307 base::Time::Exploded exploded_time; | |
308 time.UTCExplode(&exploded_time); | |
309 EXPECT_EQ(test_data[i].expected_year, exploded_time.year) | |
310 << "In iteration " << i; | |
311 EXPECT_EQ(test_data[i].expected_month, exploded_time.month) | |
312 << "In iteration " << i; | |
313 EXPECT_EQ(test_data[i].expected_day, exploded_time.day_of_month) | |
314 << "In iteration " << i; | |
315 EXPECT_EQ(test_data[i].expected_hour, exploded_time.hour) | |
316 << "In iteration " << i; | |
317 EXPECT_EQ(test_data[i].expected_minute, exploded_time.minute) | |
318 << "In iteration " << i; | |
319 EXPECT_EQ(test_data[i].expected_second, exploded_time.second) | |
320 << "In iteration " << i; | |
321 } | |
322 } | |
323 | |
324 TEST_F(PasswordStoreMacTest, TestAuthTypeSchemeTranslation) { | |
325 // Our defined types should round-trip correctly. | |
326 SecAuthenticationType auth_types[] = { kSecAuthenticationTypeHTMLForm, | |
327 kSecAuthenticationTypeHTTPBasic, | |
328 kSecAuthenticationTypeHTTPDigest }; | |
329 const int auth_count = sizeof(auth_types) / sizeof(SecAuthenticationType); | |
330 for (int i = 0; i < auth_count; ++i) { | |
331 SecAuthenticationType round_tripped_auth_type = | |
332 internal_keychain_helpers::AuthTypeForScheme( | |
333 internal_keychain_helpers::SchemeForAuthType(auth_types[i])); | |
334 EXPECT_EQ(auth_types[i], round_tripped_auth_type); | |
335 } | |
336 // Anything else should become SCHEME_OTHER and come back as Default. | |
337 PasswordForm::Scheme scheme_for_other_auth_type = | |
338 internal_keychain_helpers::SchemeForAuthType(kSecAuthenticationTypeNTLM); | |
339 SecAuthenticationType round_tripped_other_auth_type = | |
340 internal_keychain_helpers::AuthTypeForScheme(scheme_for_other_auth_type); | |
341 EXPECT_EQ(PasswordForm::SCHEME_OTHER, scheme_for_other_auth_type); | |
342 EXPECT_EQ(kSecAuthenticationTypeDefault, round_tripped_other_auth_type); | |
343 } | |
344 | |
345 TEST_F(PasswordStoreMacTest, TestKeychainToFormTranslation) { | 187 TEST_F(PasswordStoreMacTest, TestKeychainToFormTranslation) { |
346 typedef struct { | 188 typedef struct { |
347 const PasswordForm::Scheme scheme; | 189 const PasswordForm::Scheme scheme; |
348 const char* signon_realm; | 190 const char* signon_realm; |
349 const char* origin; | 191 const char* origin; |
350 const wchar_t* username; // Set to NULL to check for a blacklist entry. | 192 const wchar_t* username; // Set to NULL to check for a blacklist entry. |
351 const wchar_t* password; | 193 const wchar_t* password; |
352 const bool ssl_valid; | 194 const bool ssl_valid; |
353 const int creation_year; | 195 const int creation_year; |
354 const int creation_month; | 196 const int creation_month; |
(...skipping 21 matching lines...) Expand all Loading... |
376 2000, 1, 1, 0, 0, 0 }, | 218 2000, 1, 1, 0, 0, 0 }, |
377 { PasswordForm::SCHEME_HTML, "https://dont.remember.com/", | 219 { PasswordForm::SCHEME_HTML, "https://dont.remember.com/", |
378 "https://dont.remember.com/", NULL, NULL, true, | 220 "https://dont.remember.com/", NULL, NULL, true, |
379 2000, 1, 1, 0, 0, 0 }, | 221 2000, 1, 1, 0, 0, 0 }, |
380 { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", | 222 { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", |
381 "http://some.domain.com:4567/insecure.html", L"basic_auth_user", L"basic", | 223 "http://some.domain.com:4567/insecure.html", L"basic_auth_user", L"basic", |
382 false, 1998, 03, 30, 10, 00, 00 }, | 224 false, 1998, 03, 30, 10, 00, 00 }, |
383 { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", | 225 { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", |
384 "https://some.domain.com/", L"digest_auth_user", L"digest", true, | 226 "https://some.domain.com/", L"digest_auth_user", L"digest", true, |
385 1998, 3, 30, 10, 0, 0 }, | 227 1998, 3, 30, 10, 0, 0 }, |
| 228 { PasswordForm::SCHEME_OTHER, "http://a.server.com/", |
| 229 "http://a.server.com/", L"abc", L"123", false, |
| 230 1970, 1, 1, 0, 0, 0 }, |
386 }; | 231 }; |
387 | 232 |
388 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) { | 233 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) { |
389 // Create our fake KeychainItemRef; see MockKeychain docs. | 234 // Create our fake KeychainItemRef; see MockKeychain docs. |
390 SecKeychainItemRef keychain_item = | 235 SecKeychainItemRef keychain_item = |
391 reinterpret_cast<SecKeychainItemRef>(i + 1); | 236 reinterpret_cast<SecKeychainItemRef>(i + 1); |
392 PasswordForm form; | 237 PasswordForm form; |
393 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 238 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
394 *keychain_, keychain_item, &form); | 239 *keychain_, keychain_item, &form); |
395 | 240 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 // Use an invalid ref, to make sure errors are reported. | 274 // Use an invalid ref, to make sure errors are reported. |
430 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(99); | 275 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(99); |
431 PasswordForm form; | 276 PasswordForm form; |
432 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 277 bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
433 *keychain_, keychain_item, &form); | 278 *keychain_, keychain_item, &form); |
434 EXPECT_FALSE(parsed); | 279 EXPECT_FALSE(parsed); |
435 } | 280 } |
436 } | 281 } |
437 | 282 |
438 TEST_F(PasswordStoreMacTest, TestKeychainSearch) { | 283 TEST_F(PasswordStoreMacTest, TestKeychainSearch) { |
439 { // An HTML form we've seen. | 284 struct TestDataAndExpectation { |
440 std::vector<SecKeychainItemRef> matching_items; | 285 const PasswordFormData data; |
441 internal_keychain_helpers::FindMatchingKeychainItems( | 286 const size_t expected_matches; |
442 *keychain_, std::string("http://some.domain.com/"), | 287 }; |
443 PasswordForm::SCHEME_HTML, &matching_items); | 288 // Most fields are left blank because we don't care about them for searching. |
444 EXPECT_EQ(static_cast<size_t>(2), matching_items.size()); | 289 TestDataAndExpectation test_data[] = { |
445 FreeKeychainItems(*keychain_, &matching_items); | 290 // An HTML form we've seen. |
446 } | 291 { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", |
| 292 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 2 }, |
| 293 // An HTML form we haven't seen |
| 294 { { PasswordForm::SCHEME_HTML, "http://www.unseendomain.com/", |
| 295 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 0 }, |
| 296 // Basic auth that should match. |
| 297 { { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", |
| 298 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 1 }, |
| 299 // Basic auth with the wrong port. |
| 300 { { PasswordForm::SCHEME_BASIC, "http://some.domain.com:1111/low_security", |
| 301 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 0 }, |
| 302 // Digest auth we've saved under https, visited with http. |
| 303 { { PasswordForm::SCHEME_DIGEST, "http://some.domain.com/high_security", |
| 304 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 0 }, |
| 305 // Digest auth that should match. |
| 306 { { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", |
| 307 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, true, 0 }, 1 }, |
| 308 // Digest auth with the wrong domain. |
| 309 { { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/other_domain", |
| 310 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, true, 0 }, 0 }, |
| 311 // Garbage forms should have no matches. |
| 312 { { PasswordForm::SCHEME_HTML, "foo/bar/baz", |
| 313 NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 0 }, |
| 314 }; |
447 | 315 |
448 { // An HTML form we haven't seen | 316 MacKeychainPasswordFormAdapter keychainAdapter(keychain_); |
449 std::vector<SecKeychainItemRef> matching_items; | 317 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
450 internal_keychain_helpers::FindMatchingKeychainItems( | 318 scoped_ptr<PasswordForm> query_form( |
451 *keychain_, std::string("http://www.unseendomain.com/"), | 319 CreatePasswordFormFromData(test_data[i].data)); |
452 PasswordForm::SCHEME_HTML, &matching_items); | 320 std::vector<PasswordForm*> matching_items = |
453 EXPECT_EQ(static_cast<size_t>(0), matching_items.size()); | 321 keychainAdapter.PasswordsMatchingForm(*query_form); |
454 FreeKeychainItems(*keychain_, &matching_items); | 322 EXPECT_EQ(test_data[i].expected_matches, matching_items.size()); |
455 } | 323 STLDeleteElements(&matching_items); |
456 | |
457 { // Basic auth that should match. | |
458 std::vector<SecKeychainItemRef> matching_items; | |
459 internal_keychain_helpers::FindMatchingKeychainItems( | |
460 *keychain_, std::string("http://some.domain.com:4567/low_security"), | |
461 PasswordForm::SCHEME_BASIC, &matching_items); | |
462 EXPECT_EQ(static_cast<size_t>(1), matching_items.size()); | |
463 FreeKeychainItems(*keychain_, &matching_items); | |
464 } | |
465 | |
466 { // Basic auth with the wrong port. | |
467 std::vector<SecKeychainItemRef> matching_items; | |
468 internal_keychain_helpers::FindMatchingKeychainItems( | |
469 *keychain_, std::string("http://some.domain.com:1111/low_security"), | |
470 PasswordForm::SCHEME_BASIC, &matching_items); | |
471 EXPECT_EQ(static_cast<size_t>(0), matching_items.size()); | |
472 FreeKeychainItems(*keychain_, &matching_items); | |
473 } | |
474 | |
475 { // Digest auth we've saved under https, visited with http. | |
476 std::vector<SecKeychainItemRef> matching_items; | |
477 internal_keychain_helpers::FindMatchingKeychainItems( | |
478 *keychain_, std::string("http://some.domain.com/high_security"), | |
479 PasswordForm::SCHEME_DIGEST, &matching_items); | |
480 EXPECT_EQ(static_cast<size_t>(0), matching_items.size()); | |
481 FreeKeychainItems(*keychain_, &matching_items); | |
482 } | |
483 | |
484 { // Digest auth that should match. | |
485 std::vector<SecKeychainItemRef> matching_items; | |
486 internal_keychain_helpers::FindMatchingKeychainItems( | |
487 *keychain_, std::string("https://some.domain.com/high_security"), | |
488 PasswordForm::SCHEME_DIGEST, &matching_items); | |
489 EXPECT_EQ(static_cast<size_t>(1), matching_items.size()); | |
490 FreeKeychainItems(*keychain_, &matching_items); | |
491 } | 324 } |
492 } | 325 } |
493 | 326 |
494 TEST_F(PasswordStoreMacTest, TestKeychainExactSearch) { | 327 TEST_F(PasswordStoreMacTest, TestKeychainExactSearch) { |
495 // Test a web form entry (SCHEME_HTML). | 328 // Test a web form entry (SCHEME_HTML). |
496 { | 329 { |
497 PasswordForm search_form; | 330 PasswordForm search_form; |
498 search_form.signon_realm = std::string("http://some.domain.com/"); | 331 search_form.signon_realm = std::string("http://some.domain.com/"); |
499 search_form.origin = GURL("http://some.domain.com/insecure.html"); | 332 search_form.origin = GURL("http://some.domain.com/insecure.html"); |
500 search_form.action = GURL("http://some.domain.com/submit.cgi"); | 333 search_form.action = GURL("http://some.domain.com/submit.cgi"); |
501 search_form.username_element = std::wstring(L"username"); | 334 search_form.username_element = std::wstring(L"username"); |
502 search_form.username_value = std::wstring(L"joe_user"); | 335 search_form.username_value = std::wstring(L"joe_user"); |
503 search_form.password_element = std::wstring(L"password"); | 336 search_form.password_element = std::wstring(L"password"); |
504 search_form.preferred = true; | 337 search_form.preferred = true; |
505 SecKeychainItemRef match; | 338 SecKeychainItemRef match; |
506 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 339 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
507 search_form); | 340 search_form); |
508 EXPECT_EQ(reinterpret_cast<SecKeychainItemRef>(2), match); | 341 EXPECT_EQ(reinterpret_cast<SecKeychainItemRef>(2), match); |
509 keychain_->Free(match); | 342 keychain_->Free(match); |
510 | 343 |
511 // Make sure that the matching isn't looser than it should be. | 344 // Make sure that the matching isn't looser than it should be. |
512 PasswordForm wrong_username(search_form); | 345 PasswordForm wrong_username(search_form); |
513 wrong_username.username_value = std::wstring(L"wrong_user"); | 346 wrong_username.username_value = std::wstring(L"wrong_user"); |
514 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 347 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
515 wrong_username); | 348 wrong_username); |
516 EXPECT_EQ(NULL, match); | 349 EXPECT_EQ(NULL, match); |
517 | 350 |
518 PasswordForm wrong_path(search_form); | 351 PasswordForm wrong_path(search_form); |
519 wrong_path.origin = GURL("http://some.domain.com/elsewhere.html"); | 352 wrong_path.origin = GURL("http://some.domain.com/elsewhere.html"); |
520 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 353 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
521 wrong_path); | 354 wrong_path); |
522 EXPECT_EQ(NULL, match); | 355 EXPECT_EQ(NULL, match); |
523 | 356 |
524 PasswordForm wrong_scheme(search_form); | 357 PasswordForm wrong_scheme(search_form); |
525 wrong_scheme.scheme = PasswordForm::SCHEME_BASIC; | 358 wrong_scheme.scheme = PasswordForm::SCHEME_BASIC; |
526 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 359 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
527 wrong_scheme); | 360 wrong_scheme); |
528 EXPECT_EQ(NULL, match); | 361 EXPECT_EQ(NULL, match); |
529 | 362 |
530 // With no path, we should match the pathless Keychain entry. | 363 // With no path, we should match the pathless Keychain entry. |
531 PasswordForm no_path(search_form); | 364 PasswordForm no_path(search_form); |
532 no_path.origin = GURL("http://some.domain.com/"); | 365 no_path.origin = GURL("http://some.domain.com/"); |
533 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 366 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
534 no_path); | 367 no_path); |
535 EXPECT_EQ(reinterpret_cast<SecKeychainItemRef>(1), match); | 368 EXPECT_EQ(reinterpret_cast<SecKeychainItemRef>(1), match); |
536 keychain_->Free(match); | 369 keychain_->Free(match); |
537 | 370 |
538 // We don't store blacklist entries in the keychain, and we want to ignore | 371 // We don't store blacklist entries in the keychain, and we want to ignore |
539 // those stored by other browsers. | 372 // those stored by other browsers. |
540 PasswordForm blacklist(search_form); | 373 PasswordForm blacklist(search_form); |
541 blacklist.blacklisted_by_user = true; | 374 blacklist.blacklisted_by_user = true; |
542 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 375 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
543 blacklist); | 376 blacklist); |
544 EXPECT_EQ(NULL, match); | 377 EXPECT_EQ(NULL, match); |
545 } | 378 } |
546 | 379 |
547 // Test an http auth entry (SCHEME_BASIC, but SCHEME_DIGEST works is searched | 380 // Test an http auth entry (SCHEME_BASIC, but SCHEME_DIGEST works is searched |
548 // the same way, so this gives sufficient coverage of both). | 381 // the same way, so this gives sufficient coverage of both). |
549 { | 382 { |
550 PasswordForm search_form; | 383 PasswordForm search_form; |
551 search_form.signon_realm = | 384 search_form.signon_realm = |
552 std::string("http://some.domain.com:4567/low_security"); | 385 std::string("http://some.domain.com:4567/low_security"); |
553 search_form.origin = GURL("http://some.domain.com:4567/insecure.html"); | 386 search_form.origin = GURL("http://some.domain.com:4567/insecure.html"); |
554 search_form.username_value = std::wstring(L"basic_auth_user"); | 387 search_form.username_value = std::wstring(L"basic_auth_user"); |
555 search_form.scheme = PasswordForm::SCHEME_BASIC; | 388 search_form.scheme = PasswordForm::SCHEME_BASIC; |
556 SecKeychainItemRef match; | 389 SecKeychainItemRef match; |
557 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 390 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
558 search_form); | 391 search_form); |
559 EXPECT_EQ(reinterpret_cast<SecKeychainItemRef>(7), match); | 392 EXPECT_EQ(reinterpret_cast<SecKeychainItemRef>(7), match); |
560 keychain_->Free(match); | 393 keychain_->Free(match); |
561 | 394 |
562 // Make sure that the matching isn't looser than it should be. | 395 // Make sure that the matching isn't looser than it should be. |
563 PasswordForm wrong_username(search_form); | 396 PasswordForm wrong_username(search_form); |
564 wrong_username.username_value = std::wstring(L"wrong_user"); | 397 wrong_username.username_value = std::wstring(L"wrong_user"); |
565 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 398 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
566 wrong_username); | 399 wrong_username); |
567 EXPECT_EQ(NULL, match); | 400 EXPECT_EQ(NULL, match); |
568 | 401 |
569 PasswordForm wrong_path(search_form); | 402 PasswordForm wrong_path(search_form); |
570 wrong_path.origin = GURL("http://some.domain.com:4567/elsewhere.html"); | 403 wrong_path.origin = GURL("http://some.domain.com:4567/elsewhere.html"); |
571 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 404 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
572 wrong_path); | 405 wrong_path); |
573 EXPECT_EQ(NULL, match); | 406 EXPECT_EQ(NULL, match); |
574 | 407 |
575 PasswordForm wrong_scheme(search_form); | 408 PasswordForm wrong_scheme(search_form); |
576 wrong_scheme.scheme = PasswordForm::SCHEME_DIGEST; | 409 wrong_scheme.scheme = PasswordForm::SCHEME_DIGEST; |
577 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 410 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
578 wrong_scheme); | 411 wrong_scheme); |
579 EXPECT_EQ(NULL, match); | 412 EXPECT_EQ(NULL, match); |
580 | 413 |
581 PasswordForm wrong_port(search_form); | 414 PasswordForm wrong_port(search_form); |
582 wrong_port.signon_realm = | 415 wrong_port.signon_realm = |
583 std::string("http://some.domain.com:1234/low_security"); | 416 std::string("http://some.domain.com:1234/low_security"); |
584 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 417 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
585 wrong_port); | 418 wrong_port); |
586 EXPECT_EQ(NULL, match); | 419 EXPECT_EQ(NULL, match); |
587 | 420 |
588 PasswordForm wrong_realm(search_form); | 421 PasswordForm wrong_realm(search_form); |
589 wrong_realm.signon_realm = | 422 wrong_realm.signon_realm = |
590 std::string("http://some.domain.com:4567/incorrect"); | 423 std::string("http://some.domain.com:4567/incorrect"); |
591 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 424 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
592 wrong_realm); | 425 wrong_realm); |
593 EXPECT_EQ(NULL, match); | 426 EXPECT_EQ(NULL, match); |
594 | 427 |
595 // We don't store blacklist entries in the keychain, and we want to ignore | 428 // We don't store blacklist entries in the keychain, and we want to ignore |
596 // those stored by other browsers. | 429 // those stored by other browsers. |
597 PasswordForm blacklist(search_form); | 430 PasswordForm blacklist(search_form); |
598 blacklist.blacklisted_by_user = true; | 431 blacklist.blacklisted_by_user = true; |
599 match = internal_keychain_helpers::FindMatchingKeychainItem(*keychain_, | 432 match = internal_keychain_helpers::MatchingKeychainItem(*keychain_, |
600 blacklist); | 433 blacklist); |
601 EXPECT_EQ(NULL, match); | 434 EXPECT_EQ(NULL, match); |
602 } | 435 } |
603 } | 436 } |
604 | 437 |
605 TEST_F(PasswordStoreMacTest, TestKeychainModify) { | |
606 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(1); | |
607 EXPECT_TRUE(internal_keychain_helpers::SetKeychainItemPassword( | |
608 *keychain_, keychain_item, std::string("allnewpassword"))); | |
609 PasswordForm form; | |
610 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | |
611 keychain_item, | |
612 &form); | |
613 EXPECT_EQ(L"allnewpassword", form.password_value); | |
614 | |
615 // Check that invalid items fail to update | |
616 SecKeychainItemRef invalid_item = reinterpret_cast<SecKeychainItemRef>(1000); | |
617 EXPECT_FALSE(internal_keychain_helpers::SetKeychainItemPassword( | |
618 *keychain_, invalid_item, std::string("allnewpassword"))); | |
619 | |
620 // Check that other errors are reported (using the magic failure value). | |
621 EXPECT_FALSE(internal_keychain_helpers::SetKeychainItemPassword( | |
622 *keychain_, keychain_item, std::string("fail_me"))); | |
623 } | |
624 | |
625 TEST_F(PasswordStoreMacTest, TestKeychainAdd) { | 438 TEST_F(PasswordStoreMacTest, TestKeychainAdd) { |
626 struct TestDataAndExpectation { | 439 struct TestDataAndExpectation { |
627 PasswordFormData data; | 440 PasswordFormData data; |
628 bool should_succeed; | 441 bool should_succeed; |
629 }; | 442 }; |
630 TestDataAndExpectation test_data[] = { | 443 TestDataAndExpectation test_data[] = { |
631 // Test a variety of scheme/port/protocol/path variations. | 444 // Test a variety of scheme/port/protocol/path variations. |
632 { { PasswordForm::SCHEME_HTML, "http://web.site.com/", | 445 { { PasswordForm::SCHEME_HTML, "http://web.site.com/", |
633 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, | 446 "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, |
634 L"anonymous", L"knock-knock", false, false, 0 }, true }, | 447 L"anonymous", L"knock-knock", false, false, 0 }, true }, |
(...skipping 10 matching lines...) Expand all Loading... |
645 { { PasswordForm::SCHEME_HTML, "gobbledygook", | 458 { { PasswordForm::SCHEME_HTML, "gobbledygook", |
646 "gobbledygook", NULL, NULL, NULL, NULL, | 459 "gobbledygook", NULL, NULL, NULL, NULL, |
647 L"anonymous", L"knock-knock", false, false, 0 }, false }, | 460 L"anonymous", L"knock-knock", false, false, 0 }, false }, |
648 // Test that failing to update a duplicate (forced using the magic failure | 461 // Test that failing to update a duplicate (forced using the magic failure |
649 // password; see MockKeychain::ItemModifyAttributesAndData) is reported. | 462 // password; see MockKeychain::ItemModifyAttributesAndData) is reported. |
650 { { PasswordForm::SCHEME_HTML, "http://some.domain.com", | 463 { { PasswordForm::SCHEME_HTML, "http://some.domain.com", |
651 "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, | 464 "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, |
652 L"joe_user", L"fail_me", false, false, 0 }, false }, | 465 L"joe_user", L"fail_me", false, false, 0 }, false }, |
653 }; | 466 }; |
654 | 467 |
| 468 MacKeychainPasswordFormAdapter keychainAdapter(keychain_); |
| 469 |
655 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | 470 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
656 PasswordForm* in_form = CreatePasswordFormFromData(test_data[i].data); | 471 PasswordForm* in_form = CreatePasswordFormFromData(test_data[i].data); |
657 bool add_succeeded = | 472 bool add_succeeded = keychainAdapter.AddLogin(*in_form); |
658 internal_keychain_helpers::AddKeychainEntryForForm(*keychain_, | |
659 *in_form); | |
660 EXPECT_EQ(test_data[i].should_succeed, add_succeeded); | 473 EXPECT_EQ(test_data[i].should_succeed, add_succeeded); |
661 if (add_succeeded) { | 474 if (add_succeeded) { |
662 SecKeychainItemRef matching_item; | 475 SecKeychainItemRef matching_item; |
663 matching_item = internal_keychain_helpers::FindMatchingKeychainItem( | 476 matching_item = internal_keychain_helpers::MatchingKeychainItem( |
664 *keychain_, *in_form); | 477 *keychain_, *in_form); |
665 EXPECT_TRUE(matching_item != NULL); | 478 EXPECT_TRUE(matching_item != NULL); |
666 PasswordForm out_form; | 479 PasswordForm out_form; |
667 internal_keychain_helpers::FillPasswordFormFromKeychainItem( | 480 internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
668 *keychain_, matching_item, &out_form); | 481 *keychain_, matching_item, &out_form); |
669 EXPECT_EQ(out_form.scheme, in_form->scheme); | 482 EXPECT_EQ(out_form.scheme, in_form->scheme); |
670 EXPECT_EQ(out_form.signon_realm, in_form->signon_realm); | 483 EXPECT_EQ(out_form.signon_realm, in_form->signon_realm); |
671 EXPECT_EQ(out_form.origin, in_form->origin); | 484 EXPECT_EQ(out_form.origin, in_form->origin); |
672 EXPECT_EQ(out_form.username_value, in_form->username_value); | 485 EXPECT_EQ(out_form.username_value, in_form->username_value); |
673 EXPECT_EQ(out_form.password_value, in_form->password_value); | 486 EXPECT_EQ(out_form.password_value, in_form->password_value); |
674 keychain_->Free(matching_item); | 487 keychain_->Free(matching_item); |
675 } | 488 } |
676 delete in_form; | 489 delete in_form; |
677 } | 490 } |
678 | 491 |
679 // Test that adding duplicate item updates the existing item. | 492 // Test that adding duplicate item updates the existing item. |
680 { | 493 { |
681 PasswordFormData data = { | 494 PasswordFormData data = { |
682 PasswordForm::SCHEME_HTML, "http://some.domain.com", | 495 PasswordForm::SCHEME_HTML, "http://some.domain.com", |
683 "http://some.domain.com/insecure.html", NULL, | 496 "http://some.domain.com/insecure.html", NULL, |
684 NULL, NULL, NULL, L"joe_user", L"updated_password", false, false, 0 | 497 NULL, NULL, NULL, L"joe_user", L"updated_password", false, false, 0 |
685 }; | 498 }; |
686 PasswordForm* update_form = CreatePasswordFormFromData(data); | 499 PasswordForm* update_form = CreatePasswordFormFromData(data); |
687 EXPECT_TRUE(internal_keychain_helpers::AddKeychainEntryForForm( | 500 EXPECT_TRUE(keychainAdapter.AddLogin(*update_form)); |
688 *keychain_, *update_form)); | |
689 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(2); | 501 SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(2); |
690 PasswordForm stored_form; | 502 PasswordForm stored_form; |
691 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 503 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
692 keychain_item, | 504 keychain_item, |
693 &stored_form); | 505 &stored_form); |
694 EXPECT_EQ(update_form->password_value, stored_form.password_value); | 506 EXPECT_EQ(update_form->password_value, stored_form.password_value); |
695 delete update_form; | 507 delete update_form; |
696 } | 508 } |
697 } | 509 } |
698 | 510 |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 internal_keychain_helpers::MergePasswordForms(&keychain_forms, | 722 internal_keychain_helpers::MergePasswordForms(&keychain_forms, |
911 &database_forms, | 723 &database_forms, |
912 &merged_forms); | 724 &merged_forms); |
913 | 725 |
914 CHECK_FORMS(keychain_forms, test_data[KEYCHAIN_OUTPUT][test_case], | 726 CHECK_FORMS(keychain_forms, test_data[KEYCHAIN_OUTPUT][test_case], |
915 test_case); | 727 test_case); |
916 CHECK_FORMS(database_forms, test_data[DATABASE_OUTPUT][test_case], | 728 CHECK_FORMS(database_forms, test_data[DATABASE_OUTPUT][test_case], |
917 test_case); | 729 test_case); |
918 CHECK_FORMS(merged_forms, test_data[MERGE_OUTPUT][test_case], test_case); | 730 CHECK_FORMS(merged_forms, test_data[MERGE_OUTPUT][test_case], test_case); |
919 | 731 |
920 DeletePasswordForms(&keychain_forms); | 732 STLDeleteElements(&keychain_forms); |
921 DeletePasswordForms(&database_forms); | 733 STLDeleteElements(&database_forms); |
922 DeletePasswordForms(&merged_forms); | 734 STLDeleteElements(&merged_forms); |
923 } | 735 } |
924 } | 736 } |
OLD | NEW |