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 // OpenSSL binding for SSLClientSocket. The class layout and general principle | 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle |
6 // of operation is derived from SSLClientSocketNSS. | 6 // of operation is derived from SSLClientSocketNSS. |
7 | 7 |
8 #include "net/socket/ssl_client_socket_openssl.h" | 8 #include "net/socket/ssl_client_socket_openssl.h" |
9 | 9 |
10 #include <openssl/ssl.h> | 10 #include <openssl/ssl.h> |
11 #include <openssl/err.h> | 11 #include <openssl/err.h> |
12 | 12 |
13 #include "base/lock.h" | 13 #include "base/lock.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/openssl_util.h" | 15 #include "base/openssl_util.h" |
16 #include "base/singleton.h" | 16 #include "base/singleton.h" |
17 #include "net/base/cert_verifier.h" | 17 #include "net/base/cert_verifier.h" |
18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 19 #include "net/base/ssl_cert_request_info.h" |
19 #include "net/base/ssl_connection_status_flags.h" | 20 #include "net/base/ssl_connection_status_flags.h" |
20 #include "net/base/ssl_info.h" | 21 #include "net/base/ssl_info.h" |
21 | 22 |
22 namespace net { | 23 namespace net { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 // Enable this to see logging for state machine state transitions. | 27 // Enable this to see logging for state machine state transitions. |
27 #if 0 | 28 #if 0 |
28 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ | 29 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 base::EnsureOpenSSLInit(); | 167 base::EnsureOpenSSLInit(); |
167 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 168 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
168 DCHECK_NE(ssl_socket_data_index_, -1); | 169 DCHECK_NE(ssl_socket_data_index_, -1); |
169 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 170 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
170 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | 171 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); |
171 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); | 172 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); |
172 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); | 173 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); |
173 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); | 174 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); |
174 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); | 175 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); |
175 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); | 176 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); |
| 177 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); |
176 } | 178 } |
177 | 179 |
178 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { | 180 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { |
179 return Get()->NewSessionCallback(ssl, session); | 181 return Get()->NewSessionCallback(ssl, session); |
180 } | 182 } |
181 | 183 |
182 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { | 184 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { |
183 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); | 185 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); |
184 session_cache_.OnSessionAdded(socket->host_and_port(), session); | 186 session_cache_.OnSessionAdded(socket->host_and_port(), session); |
185 return 1; // 1 => We took ownership of |session|. | 187 return 1; // 1 => We took ownership of |session|. |
186 } | 188 } |
187 | 189 |
188 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { | 190 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { |
189 return Get()->RemoveSessionCallback(ctx, session); | 191 return Get()->RemoveSessionCallback(ctx, session); |
190 } | 192 } |
191 | 193 |
192 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { | 194 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { |
193 DCHECK(ctx == ssl_ctx()); | 195 DCHECK(ctx == ssl_ctx()); |
194 session_cache_.OnSessionRemoved(session); | 196 session_cache_.OnSessionRemoved(session); |
195 } | 197 } |
196 | 198 |
| 199 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { |
| 200 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); |
| 201 CHECK(socket); |
| 202 return socket->ClientCertRequestCallback(ssl, x509, pkey); |
| 203 } |
| 204 |
197 // This is the index used with SSL_get_ex_data to retrieve the owner | 205 // This is the index used with SSL_get_ex_data to retrieve the owner |
198 // SSLClientSocketOpenSSL object from an SSL instance. | 206 // SSLClientSocketOpenSSL object from an SSL instance. |
199 int ssl_socket_data_index_; | 207 int ssl_socket_data_index_; |
200 | 208 |
201 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | 209 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; |
202 SSLSessionCache session_cache_; | 210 SSLSessionCache session_cache_; |
203 }; | 211 }; |
204 | 212 |
205 // Utility to construct the appropriate set & clear masks for use the OpenSSL | 213 // Utility to construct the appropriate set & clear masks for use the OpenSSL |
206 // options and mode configuration functions. (SSL_set_options etc) | 214 // options and mode configuration functions. (SSL_set_options etc) |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; | 357 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; |
350 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", | 358 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", |
351 (int)peer_supports_renego_ext, 2); | 359 (int)peer_supports_renego_ext, 2); |
352 | 360 |
353 if (ssl_config_.ssl3_fallback) | 361 if (ssl_config_.ssl3_fallback) |
354 ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK; | 362 ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK; |
355 } | 363 } |
356 | 364 |
357 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( | 365 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( |
358 SSLCertRequestInfo* cert_request_info) { | 366 SSLCertRequestInfo* cert_request_info) { |
359 NOTREACHED(); | 367 cert_request_info->host_and_port = host_and_port_.ToString(); |
| 368 cert_request_info->client_certs = client_certs_; |
360 } | 369 } |
361 | 370 |
362 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( | 371 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( |
363 std::string* proto) { | 372 std::string* proto) { |
364 proto->clear(); | 373 proto->clear(); |
365 return kNextProtoUnsupported; | 374 return kNextProtoUnsupported; |
366 } | 375 } |
367 | 376 |
368 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { | 377 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { |
369 // Since Run may result in Read being called, clear |user_read_callback_| | 378 // Since Run may result in Read being called, clear |user_read_callback_| |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } while ((rv != ERR_IO_PENDING || network_moved) && | 495 } while ((rv != ERR_IO_PENDING || network_moved) && |
487 next_handshake_state_ != STATE_NONE); | 496 next_handshake_state_ != STATE_NONE); |
488 return rv; | 497 return rv; |
489 } | 498 } |
490 | 499 |
491 int SSLClientSocketOpenSSL::DoHandshake() { | 500 int SSLClientSocketOpenSSL::DoHandshake() { |
492 base::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 501 base::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
493 int net_error = net::OK; | 502 int net_error = net::OK; |
494 int rv = SSL_do_handshake(ssl_); | 503 int rv = SSL_do_handshake(ssl_); |
495 | 504 |
496 if (rv == 1) { | 505 if (client_auth_cert_needed_) { |
| 506 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
| 507 // If the handshake already succeeded (because the server requests but |
| 508 // doesn't require a client cert), we need to invalidate the SSL session |
| 509 // so that we won't try to resume the non-client-authenticated session in |
| 510 // the next handshake. This will cause the server to ask for a client |
| 511 // cert again. |
| 512 if (rv == 1) { |
| 513 // Remove from session cache but don't clear this connection. |
| 514 SSL_SESSION* session = SSL_get_session(ssl_); |
| 515 if (session) { |
| 516 int rv = SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl_), session); |
| 517 LOG_IF(WARNING, !rv) << "Couldn't invalidate SSL session: " << session; |
| 518 } |
| 519 } |
| 520 } else if (rv == 1) { |
497 if (trying_cached_session_ && logging::DEBUG_MODE) { | 521 if (trying_cached_session_ && logging::DEBUG_MODE) { |
498 DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString() | 522 DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString() |
499 << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail"); | 523 << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail"); |
500 } | 524 } |
501 | |
502 // SSL handshake is completed. Let's verify the certificate. | 525 // SSL handshake is completed. Let's verify the certificate. |
503 const bool got_cert = !!UpdateServerCert(); | 526 const bool got_cert = !!UpdateServerCert(); |
504 DCHECK(got_cert); | 527 DCHECK(got_cert); |
505 GotoState(STATE_VERIFY_CERT); | 528 GotoState(STATE_VERIFY_CERT); |
506 } else { | 529 } else { |
507 int ssl_error = SSL_get_error(ssl_, rv); | 530 int ssl_error = SSL_get_error(ssl_, rv); |
508 net_error = MapOpenSSLError(ssl_error); | 531 net_error = MapOpenSSLError(ssl_error); |
509 | 532 |
510 // If not done, stay in this state | 533 // If not done, stay in this state |
511 if (net_error == ERR_IO_PENDING) { | 534 if (net_error == ERR_IO_PENDING) { |
512 GotoState(STATE_HANDSHAKE); | 535 GotoState(STATE_HANDSHAKE); |
513 } else { | 536 } else { |
514 LOG(ERROR) << "handshake failed; returned " << rv | 537 LOG(ERROR) << "handshake failed; returned " << rv |
515 << ", SSL error code " << ssl_error | 538 << ", SSL error code " << ssl_error |
516 << ", net_error " << net_error; | 539 << ", net_error " << net_error; |
517 } | 540 } |
518 } | 541 } |
519 return net_error; | 542 return net_error; |
520 } | 543 } |
521 | 544 |
| 545 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, |
| 546 X509** x509, |
| 547 EVP_PKEY** pkey) { |
| 548 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; |
| 549 DCHECK(ssl == ssl_); |
| 550 DCHECK(*x509 == NULL); |
| 551 DCHECK(*pkey == NULL); |
| 552 |
| 553 if (!ssl_config_.send_client_cert) { |
| 554 client_auth_cert_needed_ = true; |
| 555 return -1; // Suspends handshake. |
| 556 } |
| 557 |
| 558 // Second pass: a client certificate should have been selected. |
| 559 if (ssl_config_.client_cert) { |
| 560 // TODO(joth): We need a way to lookup the private key this |
| 561 // certificate. See http://crbug.com/64951 and example code in |
| 562 // http://codereview.chromium.org/5195001/diff/6001/net/socket/ssl_client_so
cket_openssl.cc |
| 563 NOTIMPLEMENTED(); |
| 564 } |
| 565 |
| 566 // Send no client certificate. |
| 567 return 0; |
| 568 } |
| 569 |
522 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { | 570 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { |
523 DCHECK(server_cert_); | 571 DCHECK(server_cert_); |
524 GotoState(STATE_VERIFY_CERT_COMPLETE); | 572 GotoState(STATE_VERIFY_CERT_COMPLETE); |
525 int flags = 0; | 573 int flags = 0; |
526 | 574 |
527 if (ssl_config_.rev_checking_enabled) | 575 if (ssl_config_.rev_checking_enabled) |
528 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 576 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
529 if (ssl_config_.verify_ev_cert) | 577 if (ssl_config_.verify_ev_cert) |
530 flags |= X509Certificate::VERIFY_EV_CERT; | 578 flags |= X509Certificate::VERIFY_EV_CERT; |
531 verifier_.reset(new CertVerifier); | 579 verifier_.reset(new CertVerifier); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
896 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | 944 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
897 | 945 |
898 if (rv >= 0) | 946 if (rv >= 0) |
899 return rv; | 947 return rv; |
900 | 948 |
901 int err = SSL_get_error(ssl_, rv); | 949 int err = SSL_get_error(ssl_, rv); |
902 return MapOpenSSLError(err); | 950 return MapOpenSSLError(err); |
903 } | 951 } |
904 | 952 |
905 } // namespace net | 953 } // namespace net |
OLD | NEW |