OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "net/http/http_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
6 | 6 |
7 #include <math.h> // ceil | 7 #include <math.h> // ceil |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 | 1336 |
1337 rv = callback2.WaitForResult(); | 1337 rv = callback2.WaitForResult(); |
1338 EXPECT_EQ(OK, rv); | 1338 EXPECT_EQ(OK, rv); |
1339 | 1339 |
1340 response = trans->GetResponseInfo(); | 1340 response = trans->GetResponseInfo(); |
1341 ASSERT_FALSE(response == NULL); | 1341 ASSERT_FALSE(response == NULL); |
1342 EXPECT_TRUE(response->auth_challenge.get() == NULL); | 1342 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
1343 EXPECT_EQ(100, response->headers->GetContentLength()); | 1343 EXPECT_EQ(100, response->headers->GetContentLength()); |
1344 } | 1344 } |
1345 | 1345 |
| 1346 // Test the request-challenge-retry sequence for basic auth, over a connection |
| 1347 // that requires a restart when setting up an SSL tunnel. |
| 1348 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) { |
| 1349 // Configure against proxy server "myproxy:70". |
| 1350 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); |
| 1351 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
| 1352 session_deps.net_log = log.bound().net_log(); |
| 1353 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
| 1354 |
| 1355 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); |
| 1356 |
| 1357 HttpRequestInfo request; |
| 1358 request.method = "GET"; |
| 1359 request.url = GURL("https://www.google.com/"); |
| 1360 // when the no authentication data flag is set. |
| 1361 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; |
| 1362 |
| 1363 // Since we have proxy, should try to establish tunnel. |
| 1364 MockWrite data_writes1[] = { |
| 1365 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 1366 "Host: www.google.com\r\n" |
| 1367 "Proxy-Connection: keep-alive\r\n\r\n"), |
| 1368 |
| 1369 // After calling trans->RestartWithAuth(), this is the request we should |
| 1370 // be issuing -- the final header line contains the credentials. |
| 1371 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 1372 "Host: www.google.com\r\n" |
| 1373 "Proxy-Connection: keep-alive\r\n" |
| 1374 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), |
| 1375 |
| 1376 MockWrite("GET / HTTP/1.1\r\n" |
| 1377 "Host: www.google.com\r\n" |
| 1378 "Connection: keep-alive\r\n\r\n"), |
| 1379 }; |
| 1380 |
| 1381 // The proxy responds to the connect with a 407, using a persistent |
| 1382 // connection. |
| 1383 MockRead data_reads1[] = { |
| 1384 // No credentials. |
| 1385 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), |
| 1386 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 1387 MockRead("Proxy-Connection: close\r\n\r\n"), |
| 1388 |
| 1389 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), |
| 1390 |
| 1391 MockRead("HTTP/1.1 200 OK\r\n"), |
| 1392 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), |
| 1393 MockRead("Content-Length: 100\r\n\r\n"), |
| 1394 MockRead(false, OK), |
| 1395 }; |
| 1396 |
| 1397 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), |
| 1398 data_writes1, arraysize(data_writes1)); |
| 1399 session_deps.socket_factory.AddSocketDataProvider(&data1); |
| 1400 SSLSocketDataProvider ssl(true, OK); |
| 1401 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); |
| 1402 |
| 1403 TestCompletionCallback callback1; |
| 1404 |
| 1405 int rv = trans->Start(&request, &callback1, log.bound()); |
| 1406 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 1407 |
| 1408 rv = callback1.WaitForResult(); |
| 1409 EXPECT_EQ(OK, rv); |
| 1410 size_t pos = ExpectLogContainsSomewhere( |
| 1411 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, |
| 1412 NetLog::PHASE_NONE); |
| 1413 ExpectLogContainsSomewhere( |
| 1414 log.entries(), pos, |
| 1415 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, |
| 1416 NetLog::PHASE_NONE); |
| 1417 |
| 1418 const HttpResponseInfo* response = trans->GetResponseInfo(); |
| 1419 ASSERT_FALSE(response == NULL); |
| 1420 |
| 1421 EXPECT_EQ(407, response->headers->response_code()); |
| 1422 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); |
| 1423 |
| 1424 // The password prompt info should have been set in response->auth_challenge. |
| 1425 ASSERT_FALSE(response->auth_challenge.get() == NULL); |
| 1426 |
| 1427 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port); |
| 1428 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); |
| 1429 EXPECT_EQ(L"basic", response->auth_challenge->scheme); |
| 1430 |
| 1431 TestCompletionCallback callback2; |
| 1432 |
| 1433 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); |
| 1434 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 1435 |
| 1436 rv = callback2.WaitForResult(); |
| 1437 EXPECT_EQ(OK, rv); |
| 1438 |
| 1439 response = trans->GetResponseInfo(); |
| 1440 ASSERT_FALSE(response == NULL); |
| 1441 |
| 1442 EXPECT_TRUE(response->headers->IsKeepAlive()); |
| 1443 EXPECT_EQ(200, response->headers->response_code()); |
| 1444 EXPECT_EQ(100, response->headers->GetContentLength()); |
| 1445 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); |
| 1446 |
| 1447 // The password prompt info should not be set. |
| 1448 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
| 1449 } |
| 1450 |
1346 // Test the request-challenge-retry sequence for basic auth, over a keep-alive | 1451 // Test the request-challenge-retry sequence for basic auth, over a keep-alive |
1347 // proxy connection, when setting up an SSL tunnel. | 1452 // proxy connection, when setting up an SSL tunnel. |
1348 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { | 1453 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { |
1349 // Configure against proxy server "myproxy:70". | 1454 // Configure against proxy server "myproxy:70". |
1350 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); | 1455 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); |
1351 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); | 1456 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
1352 session_deps.net_log = log.bound().net_log(); | 1457 session_deps.net_log = log.bound().net_log(); |
1353 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); | 1458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
1354 | 1459 |
1355 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); | 1460 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); |
(...skipping 4933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6289 request.load_flags = 0; | 6394 request.load_flags = 0; |
6290 | 6395 |
6291 // First round goes unauthenticated through the proxy. | 6396 // First round goes unauthenticated through the proxy. |
6292 MockWrite data_writes_1[] = { | 6397 MockWrite data_writes_1[] = { |
6293 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" | 6398 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" |
6294 "Host: www.google.com\r\n" | 6399 "Host: www.google.com\r\n" |
6295 "Proxy-Connection: keep-alive\r\n" | 6400 "Proxy-Connection: keep-alive\r\n" |
6296 "\r\n"), | 6401 "\r\n"), |
6297 }; | 6402 }; |
6298 MockRead data_reads_1[] = { | 6403 MockRead data_reads_1[] = { |
| 6404 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), |
6299 MockRead("HTTP/1.1 200 OK\r\n" | 6405 MockRead("HTTP/1.1 200 OK\r\n" |
6300 "Alternate-Protocol: 443:npn-spdy/2\r\n" | 6406 "Alternate-Protocol: 443:npn-spdy/2\r\n" |
6301 "Proxy-Connection: close\r\n" | 6407 "Proxy-Connection: close\r\n" |
6302 "\r\n"), | 6408 "\r\n"), |
6303 }; | 6409 }; |
6304 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), | 6410 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), |
6305 data_writes_1, arraysize(data_writes_1)); | 6411 data_writes_1, arraysize(data_writes_1)); |
6306 | 6412 |
6307 // Second round tries to tunnel to www.google.com due to the | 6413 // Second round tries to tunnel to www.google.com due to the |
6308 // Alternate-Protocol announcement in the first round. It fails due | 6414 // Alternate-Protocol announcement in the first round. It fails due |
6309 // to a proxy authentication challenge. | 6415 // to a proxy authentication challenge. |
| 6416 // After the failure, a tunnel is established to www.google.com using |
| 6417 // Proxy-Authorization headers. There is then a SPDY request round. |
| 6418 // |
| 6419 // NOTE: Despite the "Proxy-Connection: Close", these are done on the |
| 6420 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket |
| 6421 // does a Disconnect and Connect on the same socket, rather than trying |
| 6422 // to obtain a new one. |
| 6423 // |
| 6424 // NOTE: Originally, the proxy response to the second CONNECT request |
| 6425 // simply returned another 407 so the unit test could skip the SSL connection |
| 6426 // establishment and SPDY framing issues. Alas, the |
| 6427 // retry-http-when-alternate-protocol fails logic kicks in, which was more |
| 6428 // complicated to set up expectations for than the SPDY session. |
| 6429 |
| 6430 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
| 6431 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 6432 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); |
| 6433 |
6310 MockWrite data_writes_2[] = { | 6434 MockWrite data_writes_2[] = { |
| 6435 // First connection attempt without Proxy-Authorization. |
6311 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" | 6436 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
6312 "Host: www.google.com\r\n" | 6437 "Host: www.google.com\r\n" |
6313 "Proxy-Connection: keep-alive\r\n" | 6438 "Proxy-Connection: keep-alive\r\n" |
6314 "\r\n"), | 6439 "\r\n"), |
6315 }; | |
6316 MockRead data_reads_2[] = { | |
6317 MockRead("HTTP/1.0 407 Unauthorized\r\n" | |
6318 "Proxy-Authenticate: Mock\r\n" | |
6319 "Proxy-Connection: close\r\n" | |
6320 "\r\n"), | |
6321 }; | |
6322 StaticSocketDataProvider data_2(data_reads_2, arraysize(data_reads_2), | |
6323 data_writes_2, arraysize(data_writes_2)); | |
6324 | 6440 |
6325 // Third round establishes a tunnel to www.google.com due to the | 6441 // Second connection attempt with Proxy-Authorization. |
6326 // Alternate-Protocol announcement in the first round, and does a SPDY | |
6327 // request round. | |
6328 // TODO(cbentzel): Originally, this just returned another 407 so the unit test | |
6329 // could skip the SSL connection establishment and SPDY framing issues. Alas, | |
6330 // the retry-http-when-alternate-protocol fails logic kicks in, which was more | |
6331 // complicated to set up expectations for than the SPDY session. | |
6332 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); | |
6333 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); | |
6334 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); | |
6335 | |
6336 MockWrite data_writes_3[] = { | |
6337 // TUNNEL connection established | |
6338 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" | 6442 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
6339 "Host: www.google.com\r\n" | 6443 "Host: www.google.com\r\n" |
6340 "Proxy-Connection: keep-alive\r\n" | 6444 "Proxy-Connection: keep-alive\r\n" |
6341 "Proxy-Authorization: auth_token\r\n" | 6445 "Proxy-Authorization: auth_token\r\n" |
6342 "\r\n"), | 6446 "\r\n"), |
| 6447 |
6343 // SPDY request | 6448 // SPDY request |
6344 CreateMockWrite(*req), // 3 | 6449 CreateMockWrite(*req), |
6345 }; | 6450 }; |
| 6451 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n" |
| 6452 "Proxy-Authenticate: Mock\r\n" |
| 6453 "Proxy-Connection: close\r\n" |
| 6454 "\r\n"); |
| 6455 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; |
| 6456 MockRead data_reads_2[] = { |
| 6457 // First connection attempt fails |
| 6458 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1), |
| 6459 MockRead(true, kRejectConnectResponse, |
| 6460 arraysize(kRejectConnectResponse) - 1, 1), |
6346 | 6461 |
6347 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; | 6462 // Second connection attempt passes |
6348 MockRead data_reads_3[] = { | 6463 MockRead(true, kAcceptConnectResponse, |
6349 // Proxy response | 6464 arraysize(kAcceptConnectResponse) -1, 4), |
6350 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), | 6465 |
6351 // SPDY response. | 6466 // SPDY response |
6352 CreateMockRead(*resp.get(), 4), | 6467 CreateMockRead(*resp.get(), 6), |
6353 CreateMockRead(*data.get(), 4), | 6468 CreateMockRead(*data.get(), 6), |
6354 MockRead(true, 0, 0, 4), | 6469 MockRead(true, 0, 0, 6), |
6355 }; | 6470 }; |
6356 scoped_refptr<OrderedSocketData> data_3( | 6471 scoped_refptr<OrderedSocketData> data_2( |
6357 new OrderedSocketData(data_reads_3, arraysize(data_reads_3), | 6472 new OrderedSocketData(data_reads_2, arraysize(data_reads_2), |
6358 data_writes_3, arraysize(data_writes_3))); | 6473 data_writes_2, arraysize(data_writes_2))); |
6359 | 6474 |
6360 SSLSocketDataProvider ssl(true, OK); | 6475 SSLSocketDataProvider ssl(true, OK); |
6361 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; | 6476 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; |
6362 ssl.next_proto = "spdy/2"; | 6477 ssl.next_proto = "spdy/2"; |
6363 ssl.was_npn_negotiated = true; | 6478 ssl.was_npn_negotiated = true; |
6364 | 6479 |
6365 session_deps.socket_factory.AddSocketDataProvider(&data_1); | 6480 session_deps.socket_factory.AddSocketDataProvider(&data_1); |
6366 session_deps.socket_factory.AddSocketDataProvider(&data_2); | 6481 session_deps.socket_factory.AddSocketDataProvider(data_2.get()); |
6367 session_deps.socket_factory.AddSocketDataProvider(data_3.get()); | |
6368 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); | 6482 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); |
6369 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); | 6483 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
6370 | 6484 |
6371 // First round should work and provide the Alternate-Protocol state. | 6485 // First round should work and provide the Alternate-Protocol state. |
6372 TestCompletionCallback callback_1; | 6486 TestCompletionCallback callback_1; |
6373 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session)); | 6487 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session)); |
6374 int rv = trans_1->Start(&request, &callback_1, BoundNetLog()); | 6488 int rv = trans_1->Start(&request, &callback_1, BoundNetLog()); |
6375 EXPECT_EQ(ERR_IO_PENDING, rv); | 6489 EXPECT_EQ(ERR_IO_PENDING, rv); |
6376 EXPECT_EQ(OK, callback_1.WaitForResult()); | 6490 EXPECT_EQ(OK, callback_1.WaitForResult()); |
6377 | 6491 |
(...skipping 17 matching lines...) Expand all Loading... |
6395 // what this test is all about. Make sure it happens correctly. | 6509 // what this test is all about. Make sure it happens correctly. |
6396 const GURL& request_url = auth_handler->request_url(); | 6510 const GURL& request_url = auth_handler->request_url(); |
6397 EXPECT_EQ("https", request_url.scheme()); | 6511 EXPECT_EQ("https", request_url.scheme()); |
6398 EXPECT_EQ("www.google.com", request_url.host()); | 6512 EXPECT_EQ("www.google.com", request_url.host()); |
6399 | 6513 |
6400 HttpNetworkTransaction::SetNextProtos(""); | 6514 HttpNetworkTransaction::SetNextProtos(""); |
6401 HttpNetworkTransaction::SetUseAlternateProtocols(false); | 6515 HttpNetworkTransaction::SetUseAlternateProtocols(false); |
6402 } | 6516 } |
6403 | 6517 |
6404 } // namespace net | 6518 } // namespace net |
OLD | NEW |