OLD | NEW |
---|---|
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-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 "net/http/http_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
6 | 6 |
7 #include "base/scoped_ptr.h" | 7 #include "base/scoped_ptr.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/field_trial.h" | 9 #include "base/field_trial.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 int rv = DoLoop(OK); | 186 int rv = DoLoop(OK); |
187 if (rv == ERR_IO_PENDING) | 187 if (rv == ERR_IO_PENDING) |
188 user_callback_ = callback; | 188 user_callback_ = callback; |
189 return rv; | 189 return rv; |
190 } | 190 } |
191 | 191 |
192 int HttpNetworkTransaction::RestartWithCertificate( | 192 int HttpNetworkTransaction::RestartWithCertificate( |
193 X509Certificate* client_cert, | 193 X509Certificate* client_cert, |
194 CompletionCallback* callback) { | 194 CompletionCallback* callback) { |
195 ssl_config_.client_cert = client_cert; | 195 ssl_config_.client_cert = client_cert; |
196 if (client_cert) { | |
197 session_->ssl_client_auth_cache()->Add(GetHostAndPort(request_->url), | |
198 client_cert); | |
199 } | |
196 ssl_config_.send_client_cert = true; | 200 ssl_config_.send_client_cert = true; |
197 next_state_ = STATE_INIT_CONNECTION; | 201 next_state_ = STATE_INIT_CONNECTION; |
198 // Reset the other member variables. | 202 // Reset the other member variables. |
199 // Note: this is necessary only with SSL renegotiation. | 203 // Note: this is necessary only with SSL renegotiation. |
200 ResetStateForRestart(); | 204 ResetStateForRestart(); |
201 int rv = DoLoop(OK); | 205 int rv = DoLoop(OK); |
202 if (rv == ERR_IO_PENDING) | 206 if (rv == ERR_IO_PENDING) |
203 user_callback_ = callback; | 207 user_callback_ = callback; |
204 return rv; | 208 return rv; |
205 } | 209 } |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
627 return connection_.socket()->Connect(&io_callback_); | 631 return connection_.socket()->Connect(&io_callback_); |
628 } | 632 } |
629 | 633 |
630 int HttpNetworkTransaction::DoSSLConnectComplete(int result) { | 634 int HttpNetworkTransaction::DoSSLConnectComplete(int result) { |
631 if (IsCertificateError(result)) | 635 if (IsCertificateError(result)) |
632 result = HandleCertificateError(result); | 636 result = HandleCertificateError(result); |
633 | 637 |
634 if (result == OK) { | 638 if (result == OK) { |
635 next_state_ = STATE_WRITE_HEADERS; | 639 next_state_ = STATE_WRITE_HEADERS; |
636 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 640 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { |
637 HandleCertificateRequest(); | 641 result = HandleCertificateRequest(result); |
638 } else { | 642 } else { |
639 result = HandleSSLHandshakeError(result); | 643 result = HandleSSLHandshakeError(result); |
640 } | 644 } |
641 return result; | 645 return result; |
642 } | 646 } |
643 | 647 |
644 int HttpNetworkTransaction::DoWriteHeaders() { | 648 int HttpNetworkTransaction::DoWriteHeaders() { |
645 next_state_ = STATE_WRITE_HEADERS_COMPLETE; | 649 next_state_ = STATE_WRITE_HEADERS_COMPLETE; |
646 | 650 |
647 // This is constructed lazily (instead of within our Start method), so that | 651 // This is constructed lazily (instead of within our Start method), so that |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
782 // due to SSL renegotiation. | 786 // due to SSL renegotiation. |
783 if (using_ssl_) { | 787 if (using_ssl_) { |
784 if (IsCertificateError(result)) { | 788 if (IsCertificateError(result)) { |
785 // We don't handle a certificate error during SSL renegotiation, so we | 789 // We don't handle a certificate error during SSL renegotiation, so we |
786 // have to return an error that's not in the certificate error range | 790 // have to return an error that's not in the certificate error range |
787 // (-2xx). | 791 // (-2xx). |
788 LOG(ERROR) << "Got a server certificate with error " << result | 792 LOG(ERROR) << "Got a server certificate with error " << result |
789 << " during SSL renegotiation"; | 793 << " during SSL renegotiation"; |
790 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION; | 794 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION; |
791 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 795 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { |
792 HandleCertificateRequest(); | 796 result = HandleCertificateRequest(result); |
797 if (result == OK) | |
798 return result; | |
793 } | 799 } |
794 } | 800 } |
795 | 801 |
796 if (result < 0) | 802 if (result < 0) |
797 return HandleIOError(result); | 803 return HandleIOError(result); |
798 | 804 |
799 if (result == 0 && ShouldResendRequest()) { | 805 if (result == 0 && ShouldResendRequest()) { |
800 ResetConnectionAndRequestForResend(); | 806 ResetConnectionAndRequestForResend(); |
801 return result; | 807 return result; |
802 } | 808 } |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1248 | 1254 |
1249 // Add the bad certificate to the set of allowed certificates in the | 1255 // Add the bad certificate to the set of allowed certificates in the |
1250 // SSL info object. This data structure will be consulted after calling | 1256 // SSL info object. This data structure will be consulted after calling |
1251 // RestartIgnoringLastError(). And the user will be asked interactively | 1257 // RestartIgnoringLastError(). And the user will be asked interactively |
1252 // before RestartIgnoringLastError() is ever called. | 1258 // before RestartIgnoringLastError() is ever called. |
1253 ssl_config_.allowed_bad_certs_.insert(response_.ssl_info.cert); | 1259 ssl_config_.allowed_bad_certs_.insert(response_.ssl_info.cert); |
1254 } | 1260 } |
1255 return error; | 1261 return error; |
1256 } | 1262 } |
1257 | 1263 |
1258 void HttpNetworkTransaction::HandleCertificateRequest() { | 1264 int HttpNetworkTransaction::HandleCertificateRequest(int error) { |
1265 // Assert that the socket did not send a client certificate. | |
1266 // Note: If we got a reused socket, it was created with some other | |
1267 // transaction's ssl_config_, so we need to disable this assertion. We can | |
1268 // get a certificate request on a reused socket when the server requested | |
1269 // renegotiation (rehandshake). | |
1270 // TODO(wtc): add a GetSSLParams method to SSLClientSocket so we can query | |
1271 // the SSL parameters it was created with and get rid of the reused_socket_ | |
1272 // test. | |
1273 DCHECK(reused_socket_ || !ssl_config_.send_client_cert); | |
1274 | |
1259 response_.cert_request_info = new SSLCertRequestInfo; | 1275 response_.cert_request_info = new SSLCertRequestInfo; |
1260 SSLClientSocket* ssl_socket = | 1276 SSLClientSocket* ssl_socket = |
1261 reinterpret_cast<SSLClientSocket*>(connection_.socket()); | 1277 reinterpret_cast<SSLClientSocket*>(connection_.socket()); |
1262 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info); | 1278 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info); |
1263 | 1279 |
1264 // Close the connection while the user is selecting a certificate to send | 1280 // Close the connection while the user is selecting a certificate to send |
1265 // to the server. | 1281 // to the server. |
1266 connection_.socket()->Disconnect(); | 1282 connection_.socket()->Disconnect(); |
1267 connection_.Reset(); | 1283 connection_.Reset(); |
1284 | |
1285 // If the user selected one of the certificate in client_certs for this | |
1286 // server before, use it automatically. | |
1287 X509Certificate* client_cert = session_->ssl_client_auth_cache()-> | |
1288 Lookup(GetHostAndPort(request_->url)); | |
1289 if (client_cert) { | |
1290 const std::vector<scoped_refptr<X509Certificate> >& client_certs = | |
1291 response_.cert_request_info->client_certs; | |
1292 for (size_t i = 0; i < client_certs.size(); ++i) { | |
1293 if (memcmp(&client_cert->fingerprint(), | |
eroman
2009/06/19 21:42:24
I suggesting moving this into operator==.
struct
| |
1294 &client_certs[i]->fingerprint(), | |
1295 sizeof(X509Certificate::Fingerprint)) == 0) { | |
1296 ssl_config_.client_cert = client_cert; | |
1297 ssl_config_.send_client_cert = true; | |
1298 next_state_ = STATE_INIT_CONNECTION; | |
1299 // Reset the other member variables. | |
1300 // Note: this is necessary only with SSL renegotiation. | |
1301 ResetStateForRestart(); | |
1302 return OK; | |
1303 } | |
1304 } | |
1305 } | |
1306 return error; | |
1268 } | 1307 } |
1269 | 1308 |
1270 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { | 1309 int HttpNetworkTransaction::HandleSSLHandshakeError(int error) { |
1310 if (ssl_config_.send_client_cert && | |
1311 (error == ERR_SSL_PROTOCOL_ERROR || | |
1312 error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) { | |
1313 session_->ssl_client_auth_cache()->Remove(GetHostAndPort(request_->url)); | |
1314 } | |
1315 | |
1271 switch (error) { | 1316 switch (error) { |
1272 case ERR_SSL_PROTOCOL_ERROR: | 1317 case ERR_SSL_PROTOCOL_ERROR: |
1273 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH: | 1318 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH: |
1274 if (ssl_config_.tls1_enabled) { | 1319 if (ssl_config_.tls1_enabled) { |
1275 // This could be a TLS-intolerant server or an SSL 3.0 server that | 1320 // This could be a TLS-intolerant server or an SSL 3.0 server that |
1276 // chose a TLS-only cipher suite. Turn off TLS 1.0 and retry. | 1321 // chose a TLS-only cipher suite. Turn off TLS 1.0 and retry. |
1277 ssl_config_.tls1_enabled = false; | 1322 ssl_config_.tls1_enabled = false; |
1278 connection_.socket()->Disconnect(); | 1323 connection_.socket()->Disconnect(); |
1279 connection_.Reset(); | 1324 connection_.Reset(); |
1280 next_state_ = STATE_INIT_CONNECTION; | 1325 next_state_ = STATE_INIT_CONNECTION; |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1662 host_and_port = proxy_info_.proxy_server().host_and_port(); | 1707 host_and_port = proxy_info_.proxy_server().host_and_port(); |
1663 } else { | 1708 } else { |
1664 DCHECK(target == HttpAuth::AUTH_SERVER); | 1709 DCHECK(target == HttpAuth::AUTH_SERVER); |
1665 host_and_port = GetHostAndPort(request_->url); | 1710 host_and_port = GetHostAndPort(request_->url); |
1666 } | 1711 } |
1667 auth_info->host_and_port = ASCIIToWide(host_and_port); | 1712 auth_info->host_and_port = ASCIIToWide(host_and_port); |
1668 response_.auth_challenge = auth_info; | 1713 response_.auth_challenge = auth_info; |
1669 } | 1714 } |
1670 | 1715 |
1671 } // namespace net | 1716 } // namespace net |
OLD | NEW |