1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/login/profile_auth_data.h" 6 7 #include <string> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/compiler_specific.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/run_loop.h" 14 #include "base/strings/string16.h" 15 #include "base/strings/utf_string_conversions.h" 16 #include "base/time/time.h" 17 #include "chrome/test/base/testing_profile.h" 18 #include "content/public/browser/browser_context.h" 19 #include "content/public/test/test_browser_thread_bundle.h" 20 #include "net/cookies/canonical_cookie.h" 21 #include "net/cookies/cookie_constants.h" 22 #include "net/cookies/cookie_monster.h" 23 #include "net/cookies/cookie_store.h" 24 #include "net/http/http_auth.h" 25 #include "net/http/http_auth_cache.h" 26 #include "net/http/http_network_session.h" 27 #include "net/http/http_transaction_factory.h" 28 #include "net/ssl/channel_id_service.h" 29 #include "net/ssl/channel_id_store.h" 30 #include "net/url_request/url_request_context.h" 31 #include "net/url_request/url_request_context_getter.h" 32 #include "testing/gtest/include/gtest/gtest.h" 33 #include "url/gurl.h" 34 35 namespace chromeos { 36 37 namespace { 38 39 const char kProxyAuthURL[] = "http://example.com/"; 40 const char kProxyAuthRealm[] = "realm"; 41 const char kProxyAuthChallenge[] = "challenge"; 42 const char kProxyAuthPassword1[] = "password 1"; 43 const char kProxyAuthPassword2[] = "password 2"; 44 45 const char kGAIACookieURL[] = "http://google.com/"; 46 const char kSAMLIdPCookieURL[] = "http://example.com/"; 47 const char kCookieName[] = "cookie"; 48 const char kCookieValue1[] = "value 1"; 49 const char kCookieValue2[] = "value 2"; 50 const char kGAIACookieDomain[] = "google.com"; 51 const char kSAMLIdPCookieDomain[] = "example.com"; 52 53 const char kChannelIDServerIdentifier[] = "server"; 54 const char kChannelIDPrivateKey1[] = "private key 1"; 55 const char kChannelIDPrivateKey2[] = "private key 2"; 56 const char kChannelIDCert1[] = "cert 1"; 57 const char kChannelIDCert2[] = "cert 2"; 58 59 } // namespace 60 61 class ProfileAuthDataTest : public testing::Test { 62 public: 63 // testing::Test: 64 virtual void SetUp() OVERRIDE; 65 66 void PopulateUserBrowserContext(); 67 68 void Transfer( 69 bool transfer_auth_cookies_and_channel_ids_on_first_login, 70 bool transfer_saml_auth_cookies_on_subsequent_login); 71 72 net::CookieList GetUserCookies(); 73 net::ChannelIDStore::ChannelIDList GetUserChannelIDs(); 74 75 void VerifyTransferredUserProxyAuthEntry(); 76 void VerifyUserCookies(const std::string& expected_gaia_cookie_value, 77 const std::string& expected_saml_idp_cookie_value); 78 void VerifyUserChannelID(const std::string& expected_private_key, 79 const std::string& expected_cert); 80 81 private: 82 void PopulateBrowserContext(content::BrowserContext* browser_context, 83 const std::string& proxy_auth_password, 84 const std::string& cookie_value, 85 const std::string& channel_id_private_key, 86 const std::string& channel_id_cert); 87 88 net::URLRequestContext* GetRequestContext( 89 content::BrowserContext* browser_context); 90 net::HttpAuthCache* GetProxyAuth(content::BrowserContext* browser_context); 91 net::CookieMonster* GetCookies(content::BrowserContext* browser_context); 92 net::ChannelIDStore* GetChannelIDs(content::BrowserContext* browser_context); 93 94 void QuitLoop(const net::CookieList& ignored); 95 void StoreCookieListAndQuitLoop(const net::CookieList& cookie_list); 96 void StoreChannelIDListAndQuitLoop( 97 const net::ChannelIDStore::ChannelIDList& channel_id_list); 98 99 content::TestBrowserThreadBundle thread_bundle_; 100 101 TestingProfile login_browser_context_; 102 TestingProfile user_browser_context_; 103 104 net::CookieList user_cookie_list_; 105 net::ChannelIDStore::ChannelIDList user_channel_id_list_; 106 107 scoped_ptr<base::RunLoop> run_loop_; 108 }; 109 110 void ProfileAuthDataTest::SetUp() { 111 PopulateBrowserContext(&login_browser_context_, 112 kProxyAuthPassword1, 113 kCookieValue1, 114 kChannelIDPrivateKey1, 115 kChannelIDCert1); 116 } 117 118 void ProfileAuthDataTest::PopulateUserBrowserContext() { 119 PopulateBrowserContext(&user_browser_context_, 120 kProxyAuthPassword2, 121 kCookieValue2, 122 kChannelIDPrivateKey2, 123 kChannelIDCert2); 124 } 125 126 void ProfileAuthDataTest::Transfer( 127 bool transfer_auth_cookies_and_channel_ids_on_first_login, 128 bool transfer_saml_auth_cookies_on_subsequent_login) { 129 base::RunLoop run_loop; 130 ProfileAuthData::Transfer( 131 &login_browser_context_, 132 &user_browser_context_, 133 transfer_auth_cookies_and_channel_ids_on_first_login, 134 transfer_saml_auth_cookies_on_subsequent_login, 135 run_loop.QuitClosure()); 136 run_loop.Run(); 137 if (!transfer_auth_cookies_and_channel_ids_on_first_login && 138 !transfer_saml_auth_cookies_on_subsequent_login) { 139 // When only proxy auth state is being transferred, the completion callback 140 // is invoked before the transfer has actually completed. Spin the loop once 141 // more to allow the transfer to complete. 142 base::RunLoop().RunUntilIdle(); 143 } 144 } 145 146 net::CookieList ProfileAuthDataTest::GetUserCookies() { 147 run_loop_.reset(new base::RunLoop); 148 GetCookies(&user_browser_context_)->GetAllCookiesAsync(base::Bind( 149 &ProfileAuthDataTest::StoreCookieListAndQuitLoop, 150 base::Unretained(this))); 151 run_loop_->Run(); 152 return user_cookie_list_; 153 } 154 155 net::ChannelIDStore::ChannelIDList ProfileAuthDataTest::GetUserChannelIDs() { 156 run_loop_.reset(new base::RunLoop); 157 GetChannelIDs(&user_browser_context_)->GetAllChannelIDs(base::Bind( 158 &ProfileAuthDataTest::StoreChannelIDListAndQuitLoop, 159 base::Unretained(this))); 160 run_loop_->Run(); 161 return user_channel_id_list_; 162 } 163 164 void ProfileAuthDataTest::VerifyTransferredUserProxyAuthEntry() { 165 net::HttpAuthCache::Entry* entry = 166 GetProxyAuth(&user_browser_context_)->Lookup( 167 GURL(kProxyAuthURL), 168 kProxyAuthRealm, 169 net::HttpAuth::AUTH_SCHEME_BASIC); 170 ASSERT_TRUE(entry); 171 EXPECT_EQ(base::ASCIIToUTF16(kProxyAuthPassword1), 172 entry->credentials().password()); 173 } 174 175 void ProfileAuthDataTest::VerifyUserCookies( 176 const std::string& expected_gaia_cookie_value, 177 const std::string& expected_saml_idp_cookie_value) { 178 net::CookieList user_cookies = GetUserCookies(); 179 ASSERT_EQ(2u, user_cookies.size()); 180 net::CanonicalCookie* cookie = &user_cookies[0]; 181 EXPECT_EQ(kSAMLIdPCookieURL, cookie->Source()); 182 EXPECT_EQ(kCookieName, cookie->Name()); 183 EXPECT_EQ(expected_saml_idp_cookie_value, cookie->Value()); 184 EXPECT_EQ(kSAMLIdPCookieDomain, cookie->Domain()); 185 cookie = &user_cookies[1]; 186 EXPECT_EQ(kGAIACookieURL, cookie->Source()); 187 EXPECT_EQ(kCookieName, cookie->Name()); 188 EXPECT_EQ(expected_gaia_cookie_value, cookie->Value()); 189 EXPECT_EQ(kGAIACookieDomain, cookie->Domain()); 190 } 191 192 void ProfileAuthDataTest::VerifyUserChannelID( 193 const std::string& expected_private_key, 194 const std::string& expected_cert) { 195 net::ChannelIDStore::ChannelIDList user_channel_ids = GetUserChannelIDs(); 196 ASSERT_EQ(1u, user_channel_ids.size()); 197 net::ChannelIDStore::ChannelID* channel_id = &user_channel_ids.front(); 198 EXPECT_EQ(kChannelIDServerIdentifier, channel_id->server_identifier()); 199 EXPECT_EQ(expected_private_key, channel_id->private_key()); 200 EXPECT_EQ(expected_cert, channel_id->cert()); 201 } 202 203 void ProfileAuthDataTest::PopulateBrowserContext( 204 content::BrowserContext* browser_context, 205 const std::string& proxy_auth_password, 206 const std::string& cookie_value, 207 const std::string& channel_id_private_key, 208 const std::string& channel_id_cert) { 209 GetProxyAuth(browser_context)->Add( 210 GURL(kProxyAuthURL), 211 kProxyAuthRealm, 212 net::HttpAuth::AUTH_SCHEME_BASIC, 213 kProxyAuthChallenge, 214 net::AuthCredentials(base::string16(), 215 base::ASCIIToUTF16(proxy_auth_password)), 216 std::string()); 217 218 net::CookieMonster* cookies = GetCookies(browser_context); 219 // Ensure |cookies| is fully initialized. 220 run_loop_.reset(new base::RunLoop); 221 cookies->GetAllCookiesAsync(base::Bind(&ProfileAuthDataTest::QuitLoop, 222 base::Unretained(this))); 223 run_loop_->Run(); 224 225 net::CookieList cookie_list; 226 cookie_list.push_back(net::CanonicalCookie(GURL(kGAIACookieURL), 227 kCookieName, 228 cookie_value, 229 kGAIACookieDomain, 230 std::string(), 231 base::Time(), 232 base::Time(), 233 base::Time(), 234 true, 235 false, 236 net::COOKIE_PRIORITY_DEFAULT)); 237 cookie_list.push_back(net::CanonicalCookie(GURL(kSAMLIdPCookieURL), 238 kCookieName, 239 cookie_value, 240 kSAMLIdPCookieDomain, 241 std::string(), 242 base::Time(), 243 base::Time(), 244 base::Time(), 245 true, 246 false, 247 net::COOKIE_PRIORITY_DEFAULT)); 248 cookies->ImportCookies(cookie_list); 249 250 GetChannelIDs(browser_context)->SetChannelID(kChannelIDServerIdentifier, 251 base::Time(), 252 base::Time(), 253 channel_id_private_key, 254 channel_id_cert); 255 } 256 257 net::URLRequestContext* ProfileAuthDataTest::GetRequestContext( 258 content::BrowserContext* browser_context) { 259 return browser_context->GetRequestContext()->GetURLRequestContext(); 260 } 261 262 net::HttpAuthCache* ProfileAuthDataTest::GetProxyAuth( 263 content::BrowserContext* browser_context) { 264 return GetRequestContext(browser_context)->http_transaction_factory()-> 265 GetSession()->http_auth_cache(); 266 } 267 268 net::CookieMonster* ProfileAuthDataTest::GetCookies( 269 content::BrowserContext* browser_context) { 270 return GetRequestContext(browser_context)->cookie_store()->GetCookieMonster(); 271 } 272 273 net::ChannelIDStore* ProfileAuthDataTest::GetChannelIDs( 274 content::BrowserContext* browser_context) { 275 return GetRequestContext(browser_context)->channel_id_service()-> 276 GetChannelIDStore(); 277 } 278 279 void ProfileAuthDataTest::QuitLoop(const net::CookieList& ignored) { 280 run_loop_->Quit(); 281 } 282 283 void ProfileAuthDataTest::StoreCookieListAndQuitLoop( 284 const net::CookieList& cookie_list) { 285 user_cookie_list_ = cookie_list; 286 run_loop_->Quit(); 287 } 288 289 void ProfileAuthDataTest::StoreChannelIDListAndQuitLoop( 290 const net::ChannelIDStore::ChannelIDList& channel_id_list) { 291 user_channel_id_list_ = channel_id_list; 292 run_loop_->Quit(); 293 } 294 295 // Verifies that when no transfer of auth cookies or channel IDs is requested, 296 // only the proxy auth state is transferred. 297 TEST_F(ProfileAuthDataTest, DoNotTransfer) { 298 Transfer(false, false); 299 300 VerifyTransferredUserProxyAuthEntry(); 301 EXPECT_TRUE(GetUserCookies().empty()); 302 EXPECT_TRUE(GetUserChannelIDs().empty()); 303 } 304 305 // Verifies that when the transfer of auth cookies and channel IDs on first 306 // login is requested, they do get transferred along with the proxy auth state 307 // on first login. 308 TEST_F(ProfileAuthDataTest, TransferOnFirstLoginWithNewProfile) { 309 Transfer(true, false); 310 311 VerifyTransferredUserProxyAuthEntry(); 312 VerifyUserCookies(kCookieValue1, kCookieValue1); 313 VerifyUserChannelID(kChannelIDPrivateKey1, kChannelIDCert1); 314 } 315 316 // Verifies that even if the transfer of auth cookies and channel IDs on first 317 // login is requested, only the proxy auth state is transferred on subsequent 318 // login. 319 TEST_F(ProfileAuthDataTest, TransferOnFirstLoginWithExistingProfile) { 320 PopulateUserBrowserContext(); 321 322 Transfer(true, false); 323 324 VerifyTransferredUserProxyAuthEntry(); 325 VerifyUserCookies(kCookieValue2, kCookieValue2); 326 VerifyUserChannelID(kChannelIDPrivateKey2, kChannelIDCert2); 327 } 328 329 // Verifies that when the transfer of auth cookies set by a SAML IdP on 330 // subsequent login is requested, they do get transferred along with the proxy 331 // auth state on subsequent login. 332 TEST_F(ProfileAuthDataTest, TransferOnSubsequentLogin) { 333 PopulateUserBrowserContext(); 334 335 Transfer(false, true); 336 337 VerifyTransferredUserProxyAuthEntry(); 338 VerifyUserCookies(kCookieValue2, kCookieValue1); 339 VerifyUserChannelID(kChannelIDPrivateKey2, kChannelIDCert2); 340 } 341 342 } // namespace chromeos 343