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

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

Issue 6804032: Add TLS-SRP (RFC 5054) support Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: remove "httpsv" scheme, minor NSS/OpenSSL changes Created 9 years, 8 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') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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 <set> 7 #include <set>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/format_macros.h" 11 #include "base/format_macros.h"
12 #include "base/metrics/field_trial.h" 12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/metrics/stats_counters.h" 14 #include "base/metrics/stats_counters.h"
15 #include "base/scoped_ptr.h" 15 #include "base/scoped_ptr.h"
16 #include "base/stl_util-inl.h" 16 #include "base/stl_util-inl.h"
17 #include "base/string_number_conversions.h" 17 #include "base/string_number_conversions.h"
18 #include "base/string_util.h" 18 #include "base/string_util.h"
19 #include "base/stringprintf.h" 19 #include "base/stringprintf.h"
20 #include "base/utf_string_conversions.h"
20 #include "build/build_config.h" 21 #include "build/build_config.h"
21 #include "googleurl/src/gurl.h" 22 #include "googleurl/src/gurl.h"
22 #include "net/base/auth.h" 23 #include "net/base/auth.h"
23 #include "net/base/io_buffer.h" 24 #include "net/base/io_buffer.h"
24 #include "net/base/load_flags.h" 25 #include "net/base/load_flags.h"
25 #include "net/base/net_errors.h" 26 #include "net/base/net_errors.h"
26 #include "net/base/net_util.h" 27 #include "net/base/net_util.h"
27 #include "net/base/ssl_cert_request_info.h" 28 #include "net/base/ssl_cert_request_info.h"
28 #include "net/base/ssl_connection_status_flags.h" 29 #include "net/base/ssl_connection_status_flags.h"
29 #include "net/base/upload_data_stream.h" 30 #include "net/base/upload_data_stream.h"
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 // Reset the other member variables. 191 // Reset the other member variables.
191 // Note: this is necessary only with SSL renegotiation. 192 // Note: this is necessary only with SSL renegotiation.
192 ResetStateForRestart(); 193 ResetStateForRestart();
193 next_state_ = STATE_CREATE_STREAM; 194 next_state_ = STATE_CREATE_STREAM;
194 int rv = DoLoop(OK); 195 int rv = DoLoop(OK);
195 if (rv == ERR_IO_PENDING) 196 if (rv == ERR_IO_PENDING)
196 user_callback_ = callback; 197 user_callback_ = callback;
197 return rv; 198 return rv;
198 } 199 }
199 200
201 void HttpNetworkTransaction::SetTLSLoginAuthData(AuthData* auth_data) {
202 DCHECK(!stream_request_.get()) << "Can't set TLS login on existing stream";
203 DCHECK(!stream_.get());
204 DCHECK_EQ(STATE_NONE, next_state_);
205
206 DCHECK(!auth_data->username.empty());
207 DCHECK(!auth_data->password.empty());
208
209 tls_auth_data_ = auth_data;
210 ssl_config_.tls_username = UTF16ToUTF8(auth_data->username);
211 ssl_config_.tls_password = UTF16ToUTF8(auth_data->password);
212 ssl_config_.use_tls_auth = true;
213 ssl_config_.ssl3_enabled = false;
214 ssl_config_.tls1_enabled = true;
215 }
216
217 int HttpNetworkTransaction::RestartWithTLSLogin(CompletionCallback* callback) {
218 DCHECK(!stream_request_.get());
219 DCHECK(!stream_.get());
220 DCHECK_EQ(STATE_NONE, next_state_);
221
222 DCHECK(!ssl_config_.tls_username.empty());
223 DCHECK(!ssl_config_.tls_password.empty());
224 DCHECK(ssl_config_.use_tls_auth);
225 DCHECK(ssl_config_.tls1_enabled);
226 DCHECK(!ssl_config_.ssl3_enabled);
227
228 DCHECK(response_.login_request_info.get());
229 DCHECK(tls_auth_data_.get());
230 session_->tls_client_login_cache()->Add(
231 WideToUTF8(response_.login_request_info->host_and_port),
232 tls_auth_data_);
233
234 // Reset the other member variables.
235 // Note: this is necessary only with SSL renegotiation.
236 ResetStateForRestart();
237 next_state_ = STATE_CREATE_STREAM;
238 int rv = DoLoop(OK);
239 if (rv == ERR_IO_PENDING)
240 user_callback_ = callback;
241 return rv;
242 }
243
200 int HttpNetworkTransaction::RestartWithAuth( 244 int HttpNetworkTransaction::RestartWithAuth(
201 const string16& username, 245 const string16& username,
202 const string16& password, 246 const string16& password,
203 CompletionCallback* callback) { 247 CompletionCallback* callback) {
204 HttpAuth::Target target = pending_auth_target_; 248 HttpAuth::Target target = pending_auth_target_;
205 if (target == HttpAuth::AUTH_NONE) { 249 if (target == HttpAuth::AUTH_NONE) {
206 NOTREACHED(); 250 NOTREACHED();
207 return ERR_UNEXPECTED; 251 return ERR_UNEXPECTED;
208 } 252 }
209 pending_auth_target_ = HttpAuth::AUTH_NONE; 253 pending_auth_target_ = HttpAuth::AUTH_NONE;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 367
324 next_state_ = next_state; 368 next_state_ = next_state;
325 int rv = DoLoop(OK); 369 int rv = DoLoop(OK);
326 if (rv == ERR_IO_PENDING) 370 if (rv == ERR_IO_PENDING)
327 user_callback_ = callback; 371 user_callback_ = callback;
328 return rv; 372 return rv;
329 } 373 }
330 374
331 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { 375 const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
332 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert || 376 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
333 response_.cert_request_info) ? &response_ : NULL; 377 !response_.ssl_info.tls_username.empty() ||
378 response_.cert_request_info || response_.login_request_info) ?
379 &response_ : NULL;
334 } 380 }
335 381
336 LoadState HttpNetworkTransaction::GetLoadState() const { 382 LoadState HttpNetworkTransaction::GetLoadState() const {
337 // TODO(wtc): Define a new LoadState value for the 383 // TODO(wtc): Define a new LoadState value for the
338 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request. 384 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
339 switch (next_state_) { 385 switch (next_state_) {
340 case STATE_CREATE_STREAM_COMPLETE: 386 case STATE_CREATE_STREAM_COMPLETE:
341 return stream_request_->GetLoadState(); 387 return stream_request_->GetLoadState();
342 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: 388 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
343 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE: 389 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 } 464 }
419 465
420 void HttpNetworkTransaction::OnNeedsClientAuth( 466 void HttpNetworkTransaction::OnNeedsClientAuth(
421 SSLCertRequestInfo* cert_info) { 467 SSLCertRequestInfo* cert_info) {
422 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); 468 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
423 469
424 response_.cert_request_info = cert_info; 470 response_.cert_request_info = cert_info;
425 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 471 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
426 } 472 }
427 473
474 void HttpNetworkTransaction::OnNeedsTLSLogin(
475 AuthChallengeInfo* login_info) {
476 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
477
478 response_.login_request_info = login_info;
479 OnIOComplete(ERR_TLS_CLIENT_LOGIN_NEEDED);
480 }
481
428 void HttpNetworkTransaction::OnHttpsProxyTunnelResponse( 482 void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
429 const HttpResponseInfo& response_info, 483 const HttpResponseInfo& response_info,
430 HttpStream* stream) { 484 HttpStream* stream) {
431 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); 485 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
432 486
433 headers_valid_ = true; 487 headers_valid_ = true;
434 response_ = response_info; 488 response_ = response_info;
435 stream_.reset(stream); 489 stream_.reset(stream);
436 stream_request_.reset(); // we're done with the stream request 490 stream_request_.reset(); // we're done with the stream request
437 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); 491 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 NOTREACHED() << "bad state"; 589 NOTREACHED() << "bad state";
536 rv = ERR_FAILED; 590 rv = ERR_FAILED;
537 break; 591 break;
538 } 592 }
539 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 593 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
540 594
541 return rv; 595 return rv;
542 } 596 }
543 597
544 int HttpNetworkTransaction::DoCreateStream() { 598 int HttpNetworkTransaction::DoCreateStream() {
599 DCHECK(request_);
600
601 // Set TLS login, if available.
602 if (ssl_config_.use_tls_auth) {
603 // TODO(sqs): implement some way of forcing TLS auth (as right below)
604 // if (...) ssl_config_.require_tls_auth = true;
605 if (ssl_config_.tls_username.empty()) {
606 scoped_refptr<AuthData> tls_auth_data;
607 bool found_login = session_->tls_client_login_cache()->Lookup(
608 net::GetHostAndPort(request_->url),
609 &tls_auth_data);
610 if (found_login) {
611 LOG(INFO) << "Got TLS login from cache";
612 SetTLSLoginAuthData(tls_auth_data);
613 DCHECK(!ssl_config_.tls_username.empty());
614 DCHECK(!ssl_config_.tls_password.empty());
615 } else if (ssl_config_.require_tls_auth) {
616 response_.login_request_info = new AuthChallengeInfo;
617 response_.login_request_info->host_and_port =
618 UTF8ToWide(net::GetHostAndPort(request_->url));
619 response_.login_request_info->scheme = ASCIIToWide(net::kTLSSRPScheme);
620 response_.login_request_info->over_protocol = AUTH_OVER_TLS;
621 return ERR_TLS_CLIENT_LOGIN_NEEDED;
622 }
623 }
624 }
625
545 next_state_ = STATE_CREATE_STREAM_COMPLETE; 626 next_state_ = STATE_CREATE_STREAM_COMPLETE;
546 627
547 stream_request_.reset( 628 stream_request_.reset(
548 session_->http_stream_factory()->RequestStream( 629 session_->http_stream_factory()->RequestStream(
549 request_, 630 request_,
550 &ssl_config_, 631 &ssl_config_,
551 &proxy_info_, 632 &proxy_info_,
552 session_, 633 session_,
553 this, 634 this,
554 net_log_)); 635 net_log_));
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 // by the endpoint host, request_->url, rather than considering if they were 1111 // by the endpoint host, request_->url, rather than considering if they were
1031 // generated by the SSL proxy. http://crbug.com/69329 1112 // generated by the SSL proxy. http://crbug.com/69329
1032 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { 1113 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
1033 DCHECK(request_); 1114 DCHECK(request_);
1034 if (ssl_config_.send_client_cert && 1115 if (ssl_config_.send_client_cert &&
1035 (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) { 1116 (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
1036 session_->ssl_client_auth_cache()->Remove( 1117 session_->ssl_client_auth_cache()->Remove(
1037 GetHostAndPort(request_->url)); 1118 GetHostAndPort(request_->url));
1038 } 1119 }
1039 1120
1121 // Check for TLS-SRP-related errors.
1122 if (ssl_config_.use_tls_auth) {
1123 if (ssl_config_.tls_username.empty() && ssl_config_.tls_password.empty()) {
1124 if (error == ERR_SSL_UNKNOWN_PSK_IDENTITY_ALERT) {
1125 // RFC 5054 unknown_psk_identity idiom: The Client Hello contained no
1126 // SRP username, but the server wishes to connect using an SRP cipher
1127 // suite.
1128 error = ERR_TLS_CLIENT_LOGIN_NEEDED;
1129 }
1130 } else if (!ssl_config_.tls_username.empty() &&
1131 ssl_config_.tls_password.empty()) {
1132 LOG(WARNING) << "SSL handshake error: empty TLS password";
1133 } else if (!ssl_config_.tls_username.empty() &&
1134 !ssl_config_.tls_password.empty()) {
1135 if (error == ERR_SSL_BAD_RECORD_MAC_ALERT ||
1136 error == ERR_SSL_UNKNOWN_PSK_IDENTITY_ALERT) {
1137 // The TLS-SRP login probably failed.
1138 // TODO(sqs): also verify that we did attempt to use an SRP cipher suite
1139 error = ERR_TLS_CLIENT_LOGIN_FAILED;
1140 }
1141 }
1142
1143 if (error == ERR_TLS_CLIENT_LOGIN_FAILED)
1144 session_->tls_client_login_cache()->Remove(GetHostAndPort(request_->url));
1145
1146 // Handle TLS-SRP errors now.
1147 if (error == ERR_TLS_CLIENT_LOGIN_FAILED ||
1148 error == ERR_TLS_CLIENT_LOGIN_NEEDED) {
1149 DCHECK(!response_.login_request_info.get());
1150 response_.login_request_info = new AuthChallengeInfo;
1151 response_.login_request_info->host_and_port =
1152 UTF8ToWide(GetHostAndPort(request_->url));
1153 response_.login_request_info->scheme = ASCIIToWide(net::kTLSSRPScheme);
1154 response_.login_request_info->over_protocol = AUTH_OVER_TLS;
1155 return error;
1156 }
1157 }
1158
1040 switch (error) { 1159 switch (error) {
1041 case ERR_SSL_PROTOCOL_ERROR: 1160 case ERR_SSL_PROTOCOL_ERROR:
1042 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH: 1161 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
1043 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT: 1162 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
1044 case ERR_SSL_BAD_RECORD_MAC_ALERT: 1163 case ERR_SSL_BAD_RECORD_MAC_ALERT:
1045 if (ssl_config_.tls1_enabled && 1164 if (ssl_config_.tls1_enabled &&
1046 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) { 1165 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host()) &&
1166 !ssl_config_.require_tls_auth) {
1047 // This could be a TLS-intolerant server, an SSL 3.0 server that 1167 // This could be a TLS-intolerant server, an SSL 3.0 server that
1048 // chose a TLS-only cipher suite or a server with buggy DEFLATE 1168 // chose a TLS-only cipher suite or a server with buggy DEFLATE
1049 // support. Turn off TLS 1.0, DEFLATE support and retry. 1169 // support. Turn off TLS 1.0, DEFLATE support and retry.
1170 LOG(WARNING) << "Set server TLS intolerant: " << request_->url;
1050 session_->http_stream_factory()->AddTLSIntolerantServer(request_->url); 1171 session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
1051 ResetConnectionAndRequestForResend(); 1172 ResetConnectionAndRequestForResend();
1052 error = OK; 1173 error = OK;
1053 } 1174 }
1054 break; 1175 break;
1055 case ERR_SSL_SNAP_START_NPN_MISPREDICTION: 1176 case ERR_SSL_SNAP_START_NPN_MISPREDICTION:
1056 // This means that we tried to Snap Start a connection, but we 1177 // This means that we tried to Snap Start a connection, but we
1057 // mispredicted the NPN result. This isn't a problem from the point of 1178 // mispredicted the NPN result. This isn't a problem from the point of
1058 // view of the SSL layer because the server will ignore the application 1179 // view of the SSL layer because the server will ignore the application
1059 // data in the Snap Start extension. However, at the HTTP layer, we have 1180 // data in the Snap Start extension. However, at the HTTP layer, we have
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, 1349 description = base::StringPrintf("Unknown state 0x%08X (%u)", state,
1229 state); 1350 state);
1230 break; 1351 break;
1231 } 1352 }
1232 return description; 1353 return description;
1233 } 1354 }
1234 1355
1235 #undef STATE_CASE 1356 #undef STATE_CASE
1236 1357
1237 } // namespace net 1358 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_network_transaction.h ('k') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698