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

Side by Side Diff: net/http/http_network_transaction.cc

Issue 2101014: Eliminate the establishing_tunnel_ internal state and move to explicit... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 7 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 | « net/http/http_network_transaction.h ('k') | no next file » | 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) 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 "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/field_trial.h" 8 #include "base/field_trial.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/histogram.h" 10 #include "base/histogram.h"
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)), 285 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
286 user_callback_(NULL), 286 user_callback_(NULL),
287 session_(session), 287 session_(session),
288 request_(NULL), 288 request_(NULL),
289 pac_request_(NULL), 289 pac_request_(NULL),
290 connection_(new ClientSocketHandle), 290 connection_(new ClientSocketHandle),
291 reused_socket_(false), 291 reused_socket_(false),
292 headers_valid_(false), 292 headers_valid_(false),
293 logged_response_time(false), 293 logged_response_time(false),
294 using_ssl_(false), 294 using_ssl_(false),
295 establishing_tunnel_(false),
296 using_spdy_(false), 295 using_spdy_(false),
297 alternate_protocol_mode_( 296 alternate_protocol_mode_(
298 g_use_alternate_protocols ? kUnspecified : 297 g_use_alternate_protocols ? kUnspecified :
299 kDoNotUseAlternateProtocol), 298 kDoNotUseAlternateProtocol),
300 embedded_identity_used_(false), 299 embedded_identity_used_(false),
301 default_credentials_used_(false), 300 default_credentials_used_(false),
302 read_buf_len_(0), 301 read_buf_len_(0),
303 next_state_(STATE_NONE) { 302 next_state_(STATE_NONE) {
304 session->ssl_config_service()->GetSSLConfig(&ssl_config_); 303 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
305 if (g_next_protos) 304 if (g_next_protos)
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 472
474 // We don't need to drain the response body, so we act as if we had drained 473 // We don't need to drain the response body, so we act as if we had drained
475 // the response body. 474 // the response body.
476 DidDrainBodyForAuthRestart(keep_alive); 475 DidDrainBodyForAuthRestart(keep_alive);
477 } 476 }
478 477
479 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { 478 void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
480 if (keep_alive && connection_->socket()->IsConnectedAndIdle()) { 479 if (keep_alive && connection_->socket()->IsConnectedAndIdle()) {
481 // We should call connection_->set_idle_time(), but this doesn't occur 480 // We should call connection_->set_idle_time(), but this doesn't occur
482 // often enough to be worth the trouble. 481 // often enough to be worth the trouble.
483 next_state_ = STATE_SEND_REQUEST; 482 if (using_ssl_ && proxy_info_.is_http() &&
483 ssl_connect_start_time_.is_null())
eroman 2010/05/26 03:21:27 Using the time variable feels a bit hockey.
484 next_state_ = STATE_TUNNEL_SEND_REQUEST;
485 else
486 next_state_ = STATE_SEND_REQUEST;
484 connection_->set_is_reused(true); 487 connection_->set_is_reused(true);
485 reused_socket_ = true; 488 reused_socket_ = true;
486 } else { 489 } else {
487 next_state_ = STATE_INIT_CONNECTION; 490 next_state_ = STATE_INIT_CONNECTION;
488 connection_->socket()->Disconnect(); 491 connection_->socket()->Disconnect();
489 connection_->Reset(); 492 connection_->Reset();
490 } 493 }
491 494
492 // Reset the other member variables. 495 // Reset the other member variables.
493 ResetStateForRestart(); 496 ResetStateForRestart();
494 } 497 }
495 498
496 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len, 499 int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
497 CompletionCallback* callback) { 500 CompletionCallback* callback) {
498 DCHECK(buf); 501 DCHECK(buf);
499 DCHECK_LT(0, buf_len); 502 DCHECK_LT(0, buf_len);
500 503
501 State next_state = STATE_NONE; 504 State next_state = STATE_NONE;
502 505
503 // Are we using SPDY or HTTP? 506 // Are we using SPDY or HTTP?
504 if (using_spdy_) { 507 if (using_spdy_) {
505 DCHECK(!http_stream_.get()); 508 DCHECK(!http_stream_.get());
506 DCHECK(spdy_stream_->GetResponseInfo()->headers); 509 DCHECK(spdy_stream_->GetResponseInfo()->headers);
507 next_state = STATE_SPDY_READ_BODY; 510 next_state = STATE_SPDY_READ_BODY;
508 } else { 511 } else {
509 DCHECK(!spdy_stream_.get()); 512 DCHECK(!spdy_stream_.get());
510 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
511 DCHECK(headers.get());
512 next_state = STATE_READ_BODY; 513 next_state = STATE_READ_BODY;
513 514
514 if (!connection_->is_initialized()) 515 if (!connection_->is_initialized())
515 return 0; // connection_->has been reset. Treat like EOF. 516 return 0; // connection_->has been reset. Treat like EOF.
517 }
516 518
517 if (establishing_tunnel_) { 519 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
518 // We're trying to read the body of the response but we're still trying 520 DCHECK(headers.get());
519 // to establish an SSL tunnel through the proxy. We can't read these 521 if (headers->response_code() == 407) {
eroman 2010/05/26 03:21:27 Before it was only failing in the case where the U
520 // bytes when establishing a tunnel because they might be controlled by 522 // We're trying to read the body of the response but we're still trying
521 // an active network attacker. We don't worry about this for HTTP 523 // to establish an SSL tunnel through the proxy. We can't read these
522 // because an active network attacker can already control HTTP sessions. 524 // bytes when establishing a tunnel because they might be controlled by
523 // We reach this case when the user cancels a 407 proxy auth prompt. 525 // an active network attacker. We don't worry about this for HTTP
524 // See http://crbug.com/8473. 526 // because an active network attacker can already control HTTP sessions.
525 DCHECK_EQ(407, headers->response_code()); 527 // We reach this case when the user cancels a 407 proxy auth prompt.
526 LogBlockedTunnelResponse(headers->response_code()); 528 // See http://crbug.com/8473.
527 return ERR_TUNNEL_CONNECTION_FAILED; 529 DCHECK(proxy_info_.is_http());
528 } 530 LogBlockedTunnelResponse(headers->response_code());
531 return ERR_TUNNEL_CONNECTION_FAILED;
529 } 532 }
530 533
531 read_buf_ = buf; 534 read_buf_ = buf;
532 read_buf_len_ = buf_len; 535 read_buf_len_ = buf_len;
533 536
534 next_state_ = next_state; 537 next_state_ = next_state;
535 int rv = DoLoop(OK); 538 int rv = DoLoop(OK);
536 if (rv == ERR_IO_PENDING) 539 if (rv == ERR_IO_PENDING)
537 user_callback_ = callback; 540 user_callback_ = callback;
538 return rv; 541 return rv;
539 } 542 }
540 543
541 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { 544 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
542 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert || 545 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
543 response_.cert_request_info) ? &response_ : NULL; 546 response_.cert_request_info) ? &response_ : NULL;
544 } 547 }
545 548
546 LoadState HttpNetworkTransaction::GetLoadState() const { 549 LoadState HttpNetworkTransaction::GetLoadState() const {
547 // TODO(wtc): Define a new LoadState value for the 550 // TODO(wtc): Define a new LoadState value for the
548 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request. 551 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
549 switch (next_state_) { 552 switch (next_state_) {
550 case STATE_RESOLVE_PROXY_COMPLETE: 553 case STATE_RESOLVE_PROXY_COMPLETE:
551 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; 554 return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
552 case STATE_INIT_CONNECTION_COMPLETE: 555 case STATE_INIT_CONNECTION_COMPLETE:
553 return connection_->GetLoadState(); 556 return connection_->GetLoadState();
557 case STATE_TUNNEL_SEND_REQUEST_COMPLETE:
558 case STATE_TUNNEL_READ_HEADERS_COMPLETE:
559 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
554 case STATE_SEND_REQUEST_COMPLETE: 560 case STATE_SEND_REQUEST_COMPLETE:
555 return LOAD_STATE_SENDING_REQUEST; 561 return LOAD_STATE_SENDING_REQUEST;
556 case STATE_READ_HEADERS_COMPLETE: 562 case STATE_READ_HEADERS_COMPLETE:
557 return LOAD_STATE_WAITING_FOR_RESPONSE; 563 return LOAD_STATE_WAITING_FOR_RESPONSE;
558 case STATE_READ_BODY_COMPLETE: 564 case STATE_READ_BODY_COMPLETE:
559 return LOAD_STATE_READING_RESPONSE; 565 return LOAD_STATE_READING_RESPONSE;
560 default: 566 default:
561 return LOAD_STATE_IDLE; 567 return LOAD_STATE_IDLE;
562 } 568 }
563 } 569 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 case STATE_RESOLVE_PROXY_COMPLETE: 619 case STATE_RESOLVE_PROXY_COMPLETE:
614 rv = DoResolveProxyComplete(rv); 620 rv = DoResolveProxyComplete(rv);
615 break; 621 break;
616 case STATE_INIT_CONNECTION: 622 case STATE_INIT_CONNECTION:
617 DCHECK_EQ(OK, rv); 623 DCHECK_EQ(OK, rv);
618 rv = DoInitConnection(); 624 rv = DoInitConnection();
619 break; 625 break;
620 case STATE_INIT_CONNECTION_COMPLETE: 626 case STATE_INIT_CONNECTION_COMPLETE:
621 rv = DoInitConnectionComplete(rv); 627 rv = DoInitConnectionComplete(rv);
622 break; 628 break;
629 case STATE_TUNNEL_SEND_REQUEST:
630 DCHECK_EQ(OK, rv);
631 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
632 NULL);
eroman 2010/05/26 03:21:27 nit: line these up with the paren of the previous
633 rv = DoTunnelSendRequest();
634 break;
635 case STATE_TUNNEL_SEND_REQUEST_COMPLETE:
636 rv = DoTunnelSendRequestComplete(rv);
637 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
638 NULL);
639 break;
640 case STATE_TUNNEL_READ_HEADERS:
641 DCHECK_EQ(OK, rv);
642 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
643 NULL);
644 rv = DoTunnelReadHeaders();
645 break;
646 case STATE_TUNNEL_READ_HEADERS_COMPLETE:
647 rv = DoTunnelReadHeadersComplete(rv);
648 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
649 NULL);
650 break;
623 case STATE_SSL_CONNECT: 651 case STATE_SSL_CONNECT:
624 DCHECK_EQ(OK, rv); 652 DCHECK_EQ(OK, rv);
625 rv = DoSSLConnect(); 653 rv = DoSSLConnect();
626 break; 654 break;
627 case STATE_SSL_CONNECT_COMPLETE: 655 case STATE_SSL_CONNECT_COMPLETE:
628 rv = DoSSLConnectComplete(rv); 656 rv = DoSSLConnectComplete(rv);
629 break; 657 break;
630 case STATE_SEND_REQUEST: 658 case STATE_SEND_REQUEST:
631 DCHECK_EQ(OK, rv); 659 DCHECK_EQ(OK, rv);
632 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL); 660 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 if (using_ssl_) { 942 if (using_ssl_) {
915 SSLClientSocket* ssl_socket = 943 SSLClientSocket* ssl_socket =
916 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 944 reinterpret_cast<SSLClientSocket*>(connection_->socket());
917 response_.was_npn_negotiated = ssl_socket->wasNpnNegotiated(); 945 response_.was_npn_negotiated = ssl_socket->wasNpnNegotiated();
918 } 946 }
919 next_state_ = STATE_SEND_REQUEST; 947 next_state_ = STATE_SEND_REQUEST;
920 } else { 948 } else {
921 // Now we have a TCP connected socket. Perform other connection setup as 949 // Now we have a TCP connected socket. Perform other connection setup as
922 // needed. 950 // needed.
923 UpdateConnectionTypeHistograms(CONNECTION_HTTP); 951 UpdateConnectionTypeHistograms(CONNECTION_HTTP);
924 if (using_ssl_ && (proxy_info_.is_direct() || proxy_info_.is_socks())) { 952 if (using_ssl_) {
925 next_state_ = STATE_SSL_CONNECT; 953 if (proxy_info_.is_direct() || proxy_info_.is_socks())
954 next_state_ = STATE_SSL_CONNECT;
955 else
956 next_state_ = STATE_TUNNEL_SEND_REQUEST;
926 } else { 957 } else {
927 next_state_ = STATE_SEND_REQUEST; 958 next_state_ = STATE_SEND_REQUEST;
928 if (using_ssl_)
929 establishing_tunnel_ = true;
930 } 959 }
931 } 960 }
932 961
933 return OK; 962 return OK;
934 } 963 }
935 964
965 void HttpNetworkTransaction::ClearTunnelState() {
966 http_stream_.reset();
967 request_headers_.clear();
968 response_ = HttpResponseInfo();
969 headers_valid_ = false;
970 }
971
972 int HttpNetworkTransaction::DoTunnelSendRequest() {
973 next_state_ = STATE_TUNNEL_SEND_REQUEST_COMPLETE;
974
975 // This is constructed lazily (instead of within our Start method), so that
976 // we have proxy info available.
977 if (request_headers_.empty()) {
978 // Figure out if we can/should add Proxy-Authentication headers.
979 bool have_proxy_auth =
980 HaveAuth(HttpAuth::AUTH_PROXY) ||
981 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY);
982
983 std::string request_line;
984 HttpRequestHeaders request_headers;
985 HttpRequestHeaders authorization_headers;
986
987 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization
988 // header with no credentials), we should return an error to prevent
989 // entering an infinite auth restart loop. See http://crbug.com/21050.
990 if (have_proxy_auth)
991 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers);
992
993 BuildTunnelRequest(request_, authorization_headers, endpoint_,
994 &request_line, &request_headers);
995 if (net_log_.HasListener()) {
996 net_log_.AddEvent(
997 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
998 new NetLogHttpRequestParameter(
999 request_line, request_headers));
1000 }
1001 request_headers_ = request_line + request_headers.ToString();
1002 }
1003
1004 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_));
1005
1006 return http_stream_->SendRequest(request_, request_headers_, NULL, &response_,
1007 &io_callback_);
1008 }
1009
1010 int HttpNetworkTransaction::DoTunnelSendRequestComplete(int result) {
1011 if (result < 0)
1012 return result;
eroman 2010/05/26 03:21:27 No call to ClearTunnelState() in this case?
1013
1014 next_state_ = STATE_TUNNEL_READ_HEADERS;
1015 return OK;
1016 }
1017
1018 int HttpNetworkTransaction::DoTunnelReadHeaders() {
1019 next_state_ = STATE_TUNNEL_READ_HEADERS_COMPLETE;
1020
1021 return http_stream_->ReadResponseHeaders(&io_callback_);
1022 }
1023
1024 int HttpNetworkTransaction::DoTunnelReadHeadersComplete(int result) {
1025 if (result < 0) {
1026 if (result == ERR_CONNECTION_CLOSED)
1027 result = ERR_TUNNEL_CONNECTION_FAILED;
1028 ClearTunnelState();
eroman 2010/05/26 03:21:27 The repeated calls to ClearTunnelState() seems pre
1029 return result;
1030 }
1031
1032 // Require the "HTTP/1.x" status line for SSL CONNECT.
1033 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
1034 ClearTunnelState();
1035 return ERR_TUNNEL_CONNECTION_FAILED;
1036 }
1037
1038 if (net_log_.HasListener()) {
1039 net_log_.AddEvent(
1040 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1041 new NetLogHttpResponseParameter(response_.headers));
1042 }
1043
1044 int rv = result;
1045 switch (response_.headers->response_code()) {
1046 case 200: // OK
1047 if (http_stream_->IsMoreDataBuffered()) {
1048 // The proxy sent extraneous data after the headers.
1049 rv = ERR_TUNNEL_CONNECTION_FAILED;
1050 } else {
1051 next_state_ = STATE_SSL_CONNECT;
1052 rv = OK;
1053 }
1054 break;
1055
1056 // We aren't able to CONNECT to the remote host through the proxy. We
1057 // need to be very suspicious about the response because an active network
1058 // attacker can force us into this state by masquerading as the proxy.
1059 // The only safe thing to do here is to fail the connection because our
1060 // client is expecting an SSL protected response.
1061 // See http://crbug.com/7338.
1062 case 407: // Proxy Authentication Required
1063 // We need this status code to allow proxy authentication. Our
1064 // authentication code is smart enough to avoid being tricked by an
1065 // active network attacker.
1066 headers_valid_ = true;
1067 return HandleAuthChallenge(true);
1068
1069 default:
1070 // For all other status codes, we conservatively fail the CONNECT
1071 // request.
1072 // We lose something by doing this. We have seen proxy 403, 404, and
1073 // 501 response bodies that contain a useful error message. For
1074 // example, Squid uses a 404 response to report the DNS error: "The
1075 // domain name does not exist."
1076 LogBlockedTunnelResponse(response_.headers->response_code());
1077 rv = ERR_TUNNEL_CONNECTION_FAILED;
1078 }
1079 ClearTunnelState();
1080 return rv;
1081 }
1082
936 int HttpNetworkTransaction::DoSSLConnect() { 1083 int HttpNetworkTransaction::DoSSLConnect() {
937 next_state_ = STATE_SSL_CONNECT_COMPLETE; 1084 next_state_ = STATE_SSL_CONNECT_COMPLETE;
938 1085
939 if (ContainsKey(*g_tls_intolerant_servers, GetHostAndPort(request_->url))) { 1086 if (ContainsKey(*g_tls_intolerant_servers, GetHostAndPort(request_->url))) {
940 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: " 1087 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
941 << GetHostAndPort(request_->url); 1088 << GetHostAndPort(request_->url);
942 ssl_config_.tls1_enabled = false; 1089 ssl_config_.tls1_enabled = false;
943 } 1090 }
944 1091
945 if (request_->load_flags & LOAD_VERIFY_EV_CERT) 1092 if (request_->load_flags & LOAD_VERIFY_EV_CERT)
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 } else { 1171 } else {
1025 result = HandleSSLHandshakeError(result); 1172 result = HandleSSLHandshakeError(result);
1026 } 1173 }
1027 return result; 1174 return result;
1028 } 1175 }
1029 1176
1030 int HttpNetworkTransaction::DoSendRequest() { 1177 int HttpNetworkTransaction::DoSendRequest() {
1031 next_state_ = STATE_SEND_REQUEST_COMPLETE; 1178 next_state_ = STATE_SEND_REQUEST_COMPLETE;
1032 1179
1033 UploadDataStream* request_body = NULL; 1180 UploadDataStream* request_body = NULL;
1034 if (!establishing_tunnel_ && request_->upload_data) { 1181 if (request_->upload_data) {
1035 int error_code; 1182 int error_code;
1036 request_body = UploadDataStream::Create(request_->upload_data, &error_code); 1183 request_body = UploadDataStream::Create(request_->upload_data, &error_code);
1037 if (!request_body) 1184 if (!request_body)
1038 return error_code; 1185 return error_code;
1039 } 1186 }
1040 1187
1041 // This is constructed lazily (instead of within our Start method), so that 1188 // This is constructed lazily (instead of within our Start method), so that
1042 // we have proxy info available. 1189 // we have proxy info available.
1043 if (request_headers_.empty()) { 1190 if (request_headers_.empty()) {
1044 // Figure out if we can/should add Proxy-Authentication & Authentication 1191 // Figure out if we can/should add Proxy-Authentication & Authentication
(...skipping 12 matching lines...) Expand all
1057 HttpRequestHeaders authorization_headers; 1204 HttpRequestHeaders authorization_headers;
1058 1205
1059 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization 1206 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization
1060 // header with no credentials), we should return an error to prevent 1207 // header with no credentials), we should return an error to prevent
1061 // entering an infinite auth restart loop. See http://crbug.com/21050. 1208 // entering an infinite auth restart loop. See http://crbug.com/21050.
1062 if (have_proxy_auth) 1209 if (have_proxy_auth)
1063 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers); 1210 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers);
1064 if (have_server_auth) 1211 if (have_server_auth)
1065 AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers); 1212 AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers);
1066 1213
1067 if (establishing_tunnel_) { 1214 BuildRequestHeaders(request_, authorization_headers, request_body,
1068 BuildTunnelRequest(request_, authorization_headers, endpoint_, 1215 !using_ssl_ && proxy_info_.is_http(), &request_line,
1069 &request_line, &request_headers); 1216 &request_headers);
1070 if (net_log_.HasListener()) { 1217 if (net_log_.HasListener()) {
1071 net_log_.AddEvent( 1218 net_log_.AddEvent(
1072 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 1219 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
1073 new NetLogHttpRequestParameter( 1220 new NetLogHttpRequestParameter(
1074 request_line, request_headers)); 1221 request_line, request_headers));
1075 }
1076 } else {
1077 BuildRequestHeaders(request_, authorization_headers, request_body,
1078 !using_ssl_ && proxy_info_.is_http(), &request_line,
1079 &request_headers);
1080 if (net_log_.HasListener()) {
1081 net_log_.AddEvent(
1082 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
1083 new NetLogHttpRequestParameter(
1084 request_line, request_headers));
1085 }
1086 } 1222 }
1087
1088 request_headers_ = request_line + request_headers.ToString(); 1223 request_headers_ = request_line + request_headers.ToString();
1089 } 1224 }
1090 1225
1091 headers_valid_ = false; 1226 headers_valid_ = false;
1092 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_)); 1227 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_));
1093 1228
1094 return http_stream_->SendRequest(request_, request_headers_, 1229 return http_stream_->SendRequest(request_, request_headers_,
1095 request_body, &response_, &io_callback_); 1230 request_body, &response_, &io_callback_);
1096 } 1231 }
1097 1232
1098 int HttpNetworkTransaction::DoSendRequestComplete(int result) { 1233 int HttpNetworkTransaction::DoSendRequestComplete(int result) {
1099 if (result < 0) 1234 if (result < 0)
1100 return HandleIOError(result); 1235 return HandleIOError(result);
1101 1236
1102 next_state_ = STATE_READ_HEADERS; 1237 next_state_ = STATE_READ_HEADERS;
1103 1238
1104 return OK; 1239 return OK;
1105 } 1240 }
1106 1241
1107 int HttpNetworkTransaction::DoReadHeaders() { 1242 int HttpNetworkTransaction::DoReadHeaders() {
1108 next_state_ = STATE_READ_HEADERS_COMPLETE; 1243 next_state_ = STATE_READ_HEADERS_COMPLETE;
1109 1244
1110 return http_stream_->ReadResponseHeaders(&io_callback_); 1245 return http_stream_->ReadResponseHeaders(&io_callback_);
1111 } 1246 }
1112 1247
1113 int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() { 1248 int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
1114 if (establishing_tunnel_) {
1115 // The connection was closed before the tunnel could be established.
1116 return ERR_TUNNEL_CONNECTION_FAILED;
1117 }
1118
1119 if (!response_.headers) { 1249 if (!response_.headers) {
1120 // The connection was closed before any data was sent. Likely an error 1250 // The connection was closed before any data was sent. Likely an error
1121 // rather than empty HTTP/0.9 response. 1251 // rather than empty HTTP/0.9 response.
1122 return ERR_EMPTY_RESPONSE; 1252 return ERR_EMPTY_RESPONSE;
1123 } 1253 }
1124 1254
1125 return OK; 1255 return OK;
1126 } 1256 }
1127 1257
1128 int HttpNetworkTransaction::DoReadHeadersComplete(int result) { 1258 int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 1307
1178 if (result == ERR_CONNECTION_CLOSED) { 1308 if (result == ERR_CONNECTION_CLOSED) {
1179 // For now, if we get at least some data, we do the best we can to make 1309 // For now, if we get at least some data, we do the best we can to make
1180 // sense of it and send it back up the stack. 1310 // sense of it and send it back up the stack.
1181 int rv = HandleConnectionClosedBeforeEndOfHeaders(); 1311 int rv = HandleConnectionClosedBeforeEndOfHeaders();
1182 if (rv != OK) 1312 if (rv != OK)
1183 return rv; 1313 return rv;
1184 } 1314 }
1185 1315
1186 if (net_log_.HasListener()) { 1316 if (net_log_.HasListener()) {
1187 if (establishing_tunnel_) { 1317 net_log_.AddEvent(
1188 net_log_.AddEvent( 1318 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
1189 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 1319 new NetLogHttpResponseParameter(response_.headers));
1190 new NetLogHttpResponseParameter(response_.headers));
1191 } else {
1192 net_log_.AddEvent(
1193 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
1194 new NetLogHttpResponseParameter(response_.headers));
1195 }
1196 } 1320 }
1197 1321
1198 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) { 1322 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
1199 // Require the "HTTP/1.x" status line for SSL CONNECT.
1200 if (establishing_tunnel_)
1201 return ERR_TUNNEL_CONNECTION_FAILED;
1202
1203 // HTTP/0.9 doesn't support the PUT method, so lack of response headers 1323 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
1204 // indicates a buggy server. See: 1324 // indicates a buggy server. See:
1205 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921 1325 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
1206 if (request_->method == "PUT") 1326 if (request_->method == "PUT")
1207 return ERR_METHOD_NOT_SUPPORTED; 1327 return ERR_METHOD_NOT_SUPPORTED;
1208 } 1328 }
1209 1329
1210 if (establishing_tunnel_) {
1211 switch (response_.headers->response_code()) {
1212 case 200: // OK
1213 if (http_stream_->IsMoreDataBuffered()) {
1214 // The proxy sent extraneous data after the headers.
1215 return ERR_TUNNEL_CONNECTION_FAILED;
1216 }
1217 next_state_ = STATE_SSL_CONNECT;
1218 // Reset for the real request and response headers.
1219 request_headers_.clear();
1220 http_stream_.reset(NULL);
1221 headers_valid_ = false;
1222 establishing_tunnel_ = false;
1223 // TODO(mbelshe): We should put in a test case to trip this code path.
1224 response_ = HttpResponseInfo();
1225 return OK;
1226
1227 // We aren't able to CONNECT to the remote host through the proxy. We
1228 // need to be very suspicious about the response because an active
1229 // network attacker can force us into this state by masquerading as the
1230 // proxy. The only safe thing to do here is to fail the connection
1231 // because our client is expecting an SSL protected response.
1232 // See http://crbug.com/7338.
1233 case 407: // Proxy Authentication Required
1234 // We need this status code to allow proxy authentication. Our
1235 // authentication code is smart enough to avoid being tricked by an
1236 // active network attacker.
1237 break;
1238 default:
1239 // For all other status codes, we conservatively fail the CONNECT
1240 // request.
1241 // We lose something by doing this. We have seen proxy 403, 404, and
1242 // 501 response bodies that contain a useful error message. For
1243 // example, Squid uses a 404 response to report the DNS error: "The
1244 // domain name does not exist."
1245 LogBlockedTunnelResponse(response_.headers->response_code());
1246 return ERR_TUNNEL_CONNECTION_FAILED;
1247 }
1248 }
1249
1250 // Check for an intermediate 100 Continue response. An origin server is 1330 // Check for an intermediate 100 Continue response. An origin server is
1251 // allowed to send this response even if we didn't ask for it, so we just 1331 // allowed to send this response even if we didn't ask for it, so we just
1252 // need to skip over it. 1332 // need to skip over it.
1253 // We treat any other 1xx in this same way (although in practice getting 1333 // We treat any other 1xx in this same way (although in practice getting
1254 // a 1xx that isn't a 100 is rare). 1334 // a 1xx that isn't a 100 is rare).
1255 if (response_.headers->response_code() / 100 == 1) { 1335 if (response_.headers->response_code() / 100 == 1) {
1256 response_.headers = new HttpResponseHeaders(""); 1336 response_.headers = new HttpResponseHeaders("");
1257 next_state_ = STATE_READ_HEADERS; 1337 next_state_ = STATE_READ_HEADERS;
1258 return OK; 1338 return OK;
1259 } 1339 }
1260 1340
1261 ProcessAlternateProtocol(*response_.headers, 1341 ProcessAlternateProtocol(*response_.headers,
1262 endpoint_, 1342 endpoint_,
1263 session_->mutable_alternate_protocols()); 1343 session_->mutable_alternate_protocols());
1264 1344
1265 int rv = HandleAuthChallenge(); 1345 int rv = HandleAuthChallenge(false);
1266 if (rv != OK) 1346 if (rv != OK)
1267 return rv; 1347 return rv;
1268 1348
1269 if (using_ssl_ && !establishing_tunnel_) { 1349 if (using_ssl_) {
1270 SSLClientSocket* ssl_socket = 1350 SSLClientSocket* ssl_socket =
1271 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 1351 reinterpret_cast<SSLClientSocket*>(connection_->socket());
1272 ssl_socket->GetSSLInfo(&response_.ssl_info); 1352 ssl_socket->GetSSLInfo(&response_.ssl_info);
1273 } 1353 }
1274 1354
1275 headers_valid_ = true; 1355 headers_valid_ = true;
1276 return OK; 1356 return OK;
1277 } 1357 }
1278 1358
1279 int HttpNetworkTransaction::DoResolveCanonicalName() { 1359 int HttpNetworkTransaction::DoResolveCanonicalName() {
(...skipping 18 matching lines...) Expand all
1298 DCHECK_GT(read_buf_len_, 0); 1378 DCHECK_GT(read_buf_len_, 0);
1299 DCHECK(connection_->is_initialized()); 1379 DCHECK(connection_->is_initialized());
1300 1380
1301 next_state_ = STATE_READ_BODY_COMPLETE; 1381 next_state_ = STATE_READ_BODY_COMPLETE;
1302 return http_stream_->ReadResponseBody(read_buf_, read_buf_len_, 1382 return http_stream_->ReadResponseBody(read_buf_, read_buf_len_,
1303 &io_callback_); 1383 &io_callback_);
1304 } 1384 }
1305 1385
1306 int HttpNetworkTransaction::DoReadBodyComplete(int result) { 1386 int HttpNetworkTransaction::DoReadBodyComplete(int result) {
1307 // We are done with the Read call. 1387 // We are done with the Read call.
1308 DCHECK(!establishing_tunnel_) <<
1309 "We should never read a response body of a tunnel.";
1310
1311 bool done = false, keep_alive = false; 1388 bool done = false, keep_alive = false;
1312 if (result <= 0) 1389 if (result <= 0)
1313 done = true; 1390 done = true;
1314 1391
1315 if (http_stream_->IsResponseBodyComplete()) { 1392 if (http_stream_->IsResponseBodyComplete()) {
1316 done = true; 1393 done = true;
1317 if (http_stream_->CanFindEndOfResponse()) 1394 if (http_stream_->CanFindEndOfResponse())
1318 keep_alive = GetResponseHeaders()->IsKeepAlive(); 1395 keep_alive = GetResponseHeaders()->IsKeepAlive();
1319 } 1396 }
1320 1397
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
1714 } 1791 }
1715 1792
1716 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const { 1793 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
1717 return response_.headers; 1794 return response_.headers;
1718 } 1795 }
1719 1796
1720 bool HttpNetworkTransaction::ShouldResendRequest(int error) const { 1797 bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
1721 // NOTE: we resend a request only if we reused a keep-alive connection. 1798 // NOTE: we resend a request only if we reused a keep-alive connection.
1722 // This automatically prevents an infinite resend loop because we'll run 1799 // This automatically prevents an infinite resend loop because we'll run
1723 // out of the cached keep-alive connections eventually. 1800 // out of the cached keep-alive connections eventually.
1724 if (establishing_tunnel_ || 1801 if (!connection_->ShouldResendFailedRequest(error) ||
1725 !connection_->ShouldResendFailedRequest(error) ||
1726 GetResponseHeaders()) { // We have received some response headers. 1802 GetResponseHeaders()) { // We have received some response headers.
1727 return false; 1803 return false;
1728 } 1804 }
1729 return true; 1805 return true;
1730 } 1806 }
1731 1807
1732 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() { 1808 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
1733 connection_->socket()->Disconnect(); 1809 connection_->socket()->Disconnect();
1734 connection_->Reset(); 1810 connection_->Reset();
1735 // We need to clear request_headers_ because it contains the real request 1811 // We need to clear request_headers_ because it contains the real request
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1794 // there was nothing left to fall-back to, so fail the transaction 1870 // there was nothing left to fall-back to, so fail the transaction
1795 // with the last connection error we got. 1871 // with the last connection error we got.
1796 // TODO(eroman): This is a confusing contract, make it more obvious. 1872 // TODO(eroman): This is a confusing contract, make it more obvious.
1797 rv = error; 1873 rv = error;
1798 } 1874 }
1799 1875
1800 return rv; 1876 return rv;
1801 } 1877 }
1802 1878
1803 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const { 1879 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
1804 return (!using_ssl_ && proxy_info_.is_http()) || establishing_tunnel_; 1880 return !using_ssl_ && proxy_info_.is_http();
1805 } 1881 }
1806 1882
1807 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { 1883 bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
1808 return !establishing_tunnel_ && 1884 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
1809 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
1810 } 1885 }
1811 1886
1812 void HttpNetworkTransaction::AddAuthorizationHeader( 1887 void HttpNetworkTransaction::AddAuthorizationHeader(
1813 HttpAuth::Target target, HttpRequestHeaders* authorization_headers) const { 1888 HttpAuth::Target target, HttpRequestHeaders* authorization_headers) const {
1814 DCHECK(HaveAuth(target)); 1889 DCHECK(HaveAuth(target));
1815 1890
1816 // Add a Authorization/Proxy-Authorization header line. 1891 // Add a Authorization/Proxy-Authorization header line.
1817 std::string auth_token; 1892 std::string auth_token;
1818 int rv; 1893 int rv;
1819 if (auth_identity_[target].source == 1894 if (auth_identity_[target].source ==
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
2000 // response header. 2075 // response header.
2001 iter = NULL; 2076 iter = NULL;
2002 while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) { 2077 while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) {
2003 msg.append("\n Has header Proxy-Support: "); 2078 msg.append("\n Has header Proxy-Support: ");
2004 msg.append(header_val); 2079 msg.append(header_val);
2005 } 2080 }
2006 2081
2007 return msg; 2082 return msg;
2008 } 2083 }
2009 2084
2010 int HttpNetworkTransaction::HandleAuthChallenge() { 2085 int HttpNetworkTransaction::HandleAuthChallenge(bool establishing_tunnel) {
2011 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders(); 2086 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
2012 DCHECK(headers); 2087 DCHECK(headers);
2013 2088
2014 int status = headers->response_code(); 2089 int status = headers->response_code();
2015 if (status != 401 && status != 407) 2090 if (status != 401 && status != 407)
2016 return OK; 2091 return OK;
2017 HttpAuth::Target target = status == 407 ? 2092 HttpAuth::Target target = status == 407 ?
2018 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; 2093 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
2019 GURL auth_origin = PossiblyInvalidAuthOrigin(target); 2094 GURL auth_origin = PossiblyInvalidAuthOrigin(target);
2020 2095
(...skipping 22 matching lines...) Expand all
2043 2118
2044 if (target != HttpAuth::AUTH_SERVER || 2119 if (target != HttpAuth::AUTH_SERVER ||
2045 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA)) { 2120 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA)) {
2046 // Find the best authentication challenge that we support. 2121 // Find the best authentication challenge that we support.
2047 HttpAuth::ChooseBestChallenge(session_->http_auth_handler_factory(), 2122 HttpAuth::ChooseBestChallenge(session_->http_auth_handler_factory(),
2048 headers, target, 2123 headers, target,
2049 auth_origin, &auth_handler_[target]); 2124 auth_origin, &auth_handler_[target]);
2050 } 2125 }
2051 2126
2052 if (!auth_handler_[target]) { 2127 if (!auth_handler_[target]) {
2053 if (establishing_tunnel_) { 2128 if (establishing_tunnel) {
2054 LOG(ERROR) << "Can't perform auth to the " << AuthTargetString(target) 2129 LOG(ERROR) << "Can't perform auth to the " << AuthTargetString(target)
2055 << " " << auth_origin << " when establishing a tunnel" 2130 << " " << auth_origin << " when establishing a tunnel"
2056 << AuthChallengeLogMessage(); 2131 << AuthChallengeLogMessage();
2057 2132
2058 // We are establishing a tunnel, we can't show the error page because an 2133 // We are establishing a tunnel, we can't show the error page because an
2059 // active network attacker could control its contents. Instead, we just 2134 // active network attacker could control its contents. Instead, we just
2060 // fail to establish the tunnel. 2135 // fail to establish the tunnel.
2061 DCHECK(target == HttpAuth::AUTH_PROXY); 2136 DCHECK(target == HttpAuth::AUTH_PROXY);
2062 return ERR_PROXY_AUTH_REQUESTED; 2137 return ERR_PROXY_AUTH_REQUESTED;
2063 } 2138 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2126 endpoint_); 2201 endpoint_);
2127 2202
2128 alternate_protocol_mode_ = kDoNotUseAlternateProtocol; 2203 alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
2129 if (connection_->socket()) 2204 if (connection_->socket())
2130 connection_->socket()->Disconnect(); 2205 connection_->socket()->Disconnect();
2131 connection_->Reset(); 2206 connection_->Reset();
2132 next_state_ = STATE_INIT_CONNECTION; 2207 next_state_ = STATE_INIT_CONNECTION;
2133 } 2208 }
2134 2209
2135 } // namespace net 2210 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_network_transaction.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698