| 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 |