Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <errno.h> | 10 #include <errno.h> |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 ssl_(NULL), | 356 ssl_(NULL), |
| 357 transport_bio_(NULL), | 357 transport_bio_(NULL), |
| 358 transport_(transport_socket.Pass()), | 358 transport_(transport_socket.Pass()), |
| 359 host_and_port_(host_and_port), | 359 host_and_port_(host_and_port), |
| 360 ssl_config_(ssl_config), | 360 ssl_config_(ssl_config), |
| 361 ssl_session_cache_shard_(context.ssl_session_cache_shard), | 361 ssl_session_cache_shard_(context.ssl_session_cache_shard), |
| 362 trying_cached_session_(false), | 362 trying_cached_session_(false), |
| 363 next_handshake_state_(STATE_NONE), | 363 next_handshake_state_(STATE_NONE), |
| 364 npn_status_(kNextProtoUnsupported), | 364 npn_status_(kNextProtoUnsupported), |
| 365 channel_id_xtn_negotiated_(false), | 365 channel_id_xtn_negotiated_(false), |
| 366 ran_handshake_finished_callback_(false), | |
| 367 marked_session_as_good_(false), | |
| 366 net_log_(transport_->socket()->NetLog()) { | 368 net_log_(transport_->socket()->NetLog()) { |
| 367 } | 369 } |
| 368 | 370 |
| 369 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | 371 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { |
| 370 Disconnect(); | 372 Disconnect(); |
| 371 } | 373 } |
| 372 | 374 |
| 373 bool SSLClientSocketOpenSSL::InSessionCache() const { | 375 bool SSLClientSocketOpenSSL::InSessionCache() const { |
| 374 SSLContext* context = SSLContext::GetInstance(); | 376 SSLContext* context = SSLContext::GetInstance(); |
| 375 std::string cache_key = GetSessionCacheKey(); | 377 std::string cache_key = GetSessionCacheKey(); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) { | 430 int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) { |
| 429 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT); | 431 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT); |
| 430 | 432 |
| 431 // Set up new ssl object. | 433 // Set up new ssl object. |
| 432 int rv = Init(); | 434 int rv = Init(); |
| 433 if (rv != OK) { | 435 if (rv != OK) { |
| 434 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 436 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
| 435 return rv; | 437 return rv; |
| 436 } | 438 } |
| 437 | 439 |
| 438 if (!handshake_completion_callback_.is_null()) { | |
| 439 SSLContext* context = SSLContext::GetInstance(); | |
| 440 context->session_cache()->SetSessionAddedCallback( | |
| 441 ssl_, | |
| 442 base::Bind(&SSLClientSocketOpenSSL::OnHandshakeCompletion, | |
| 443 base::Unretained(this))); | |
| 444 } | |
| 445 | |
| 446 // Set SSL to client mode. Handshake happens in the loop below. | 440 // Set SSL to client mode. Handshake happens in the loop below. |
| 447 SSL_set_connect_state(ssl_); | 441 SSL_set_connect_state(ssl_); |
| 448 | 442 |
| 449 GotoState(STATE_HANDSHAKE); | 443 GotoState(STATE_HANDSHAKE); |
| 450 rv = DoHandshakeLoop(OK); | 444 rv = DoHandshakeLoop(OK); |
| 451 if (rv == ERR_IO_PENDING) { | 445 if (rv == ERR_IO_PENDING) { |
| 452 user_connect_callback_ = callback; | 446 user_connect_callback_ = callback; |
| 453 } else { | 447 } else { |
| 454 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 448 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
| 455 if (rv < OK) | 449 if (rv < OK) |
| 456 OnHandshakeCompletion(); | 450 OnHandshakeCompletion(); |
| 457 } | 451 } |
| 458 | 452 |
| 459 return rv > OK ? OK : rv; | 453 return rv > OK ? OK : rv; |
| 460 } | 454 } |
| 461 | 455 |
| 462 void SSLClientSocketOpenSSL::Disconnect() { | 456 void SSLClientSocketOpenSSL::Disconnect() { |
| 463 // If a handshake was pending (Connect() had been called), notify interested | 457 // If a handshake was pending (Connect() had been called), notify interested |
| 464 // parties that it's been aborted now. If the handshake had already | 458 // parties that it's been aborted now. If the handshake had already |
| 465 // completed, this is a no-op. | 459 // completed, this is a no-op. |
| 466 OnHandshakeCompletion(); | 460 OnHandshakeCompletion(); |
| 467 if (ssl_) { | 461 if (ssl_) { |
| 468 SSLContext* context = SSLContext::GetInstance(); | |
| 469 context->session_cache()->RemoveSessionAddedCallback(ssl_); | |
| 470 // Calling SSL_shutdown prevents the session from being marked as | 462 // Calling SSL_shutdown prevents the session from being marked as |
| 471 // unresumable. | 463 // unresumable. |
| 472 SSL_shutdown(ssl_); | 464 SSL_shutdown(ssl_); |
| 473 SSL_free(ssl_); | 465 SSL_free(ssl_); |
| 474 ssl_ = NULL; | 466 ssl_ = NULL; |
| 475 } | 467 } |
| 476 if (transport_bio_) { | 468 if (transport_bio_) { |
| 477 BIO_free_all(transport_bio_); | 469 BIO_free_all(transport_bio_); |
| 478 transport_bio_ = NULL; | 470 transport_bio_ = NULL; |
| 479 } | 471 } |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 680 } | 672 } |
| 681 | 673 |
| 682 int SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { | 674 int SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { |
| 683 return transport_->socket()->SetReceiveBufferSize(size); | 675 return transport_->socket()->SetReceiveBufferSize(size); |
| 684 } | 676 } |
| 685 | 677 |
| 686 int SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { | 678 int SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { |
| 687 return transport_->socket()->SetSendBufferSize(size); | 679 return transport_->socket()->SetSendBufferSize(size); |
| 688 } | 680 } |
| 689 | 681 |
| 682 // static | |
| 683 void SSLClientSocketOpenSSL::InfoCallback(const SSL* ssl, | |
| 684 int result, | |
| 685 int /*unused*/) { | |
|
wtc
2014/08/07 20:04:04
The second parameter should be named "type". The t
| |
| 686 SSLClientSocketOpenSSL* ssl_socket = | |
| 687 SSLContext::GetInstance()->GetClientSocketFromSSL(ssl); | |
|
wtc
2014/08/07 20:04:03
Move this into the if block because it is only use
| |
| 688 if (result == SSL_CB_HANDSHAKE_DONE) { | |
| 689 ssl_socket->ran_handshake_finished_callback_ = true; | |
| 690 ssl_socket->CheckIfHandshakeFinished(); | |
| 691 } | |
| 692 } | |
| 693 | |
| 690 int SSLClientSocketOpenSSL::Init() { | 694 int SSLClientSocketOpenSSL::Init() { |
| 691 DCHECK(!ssl_); | 695 DCHECK(!ssl_); |
| 692 DCHECK(!transport_bio_); | 696 DCHECK(!transport_bio_); |
| 693 | 697 |
| 694 SSLContext* context = SSLContext::GetInstance(); | 698 SSLContext* context = SSLContext::GetInstance(); |
| 695 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 699 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 696 | 700 |
| 697 ssl_ = SSL_new(context->ssl_ctx()); | 701 ssl_ = SSL_new(context->ssl_ctx()); |
| 698 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) | 702 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) |
| 699 return ERR_UNEXPECTED; | 703 return ERR_UNEXPECTED; |
| 700 | 704 |
| 701 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) | 705 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) |
| 702 return ERR_UNEXPECTED; | 706 return ERR_UNEXPECTED; |
| 703 | 707 |
| 708 // Set an OpenSSL callback to monitor this SSL*'s connection. | |
| 709 SSL_set_info_callback(ssl_, &InfoCallback); | |
| 710 | |
| 704 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( | 711 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( |
| 705 ssl_, GetSessionCacheKey()); | 712 ssl_, GetSessionCacheKey()); |
| 706 | 713 |
| 707 BIO* ssl_bio = NULL; | 714 BIO* ssl_bio = NULL; |
| 708 // 0 => use default buffer sizes. | 715 // 0 => use default buffer sizes. |
| 709 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 716 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
| 710 return ERR_UNEXPECTED; | 717 return ERR_UNEXPECTED; |
| 711 DCHECK(ssl_bio); | 718 DCHECK(ssl_bio); |
| 712 DCHECK(transport_bio_); | 719 DCHECK(transport_bio_); |
| 713 | 720 |
| 714 // Install a callback on OpenSSL's end to plumb transport errors through. | 721 // Install a callback on OpenSSL's end to plumb transport errors through. |
| 715 BIO_set_callback(ssl_bio, &SSLClientSocketOpenSSL::BIOCallback); | 722 BIO_set_callback(ssl_bio, &SSLClientSocketOpenSSL::BIOCallback); |
|
wtc
2014/08/07 20:04:03
Nit: Could you delete "SSLClientSocketOpenSSL::" ?
| |
| 716 BIO_set_callback_arg(ssl_bio, reinterpret_cast<char*>(this)); | 723 BIO_set_callback_arg(ssl_bio, reinterpret_cast<char*>(this)); |
| 717 | 724 |
| 718 SSL_set_bio(ssl_, ssl_bio, ssl_bio); | 725 SSL_set_bio(ssl_, ssl_bio, ssl_bio); |
| 719 | 726 |
| 720 // OpenSSL defaults some options to on, others to off. To avoid ambiguity, | 727 // OpenSSL defaults some options to on, others to off. To avoid ambiguity, |
| 721 // set everything we care about to an absolute value. | 728 // set everything we care about to an absolute value. |
| 722 SslSetClearMask options; | 729 SslSetClearMask options; |
| 723 options.ConfigureFlag(SSL_OP_NO_SSLv2, true); | 730 options.ConfigureFlag(SSL_OP_NO_SSLv2, true); |
| 724 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); | 731 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); |
| 725 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled); | 732 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1025 net_log_); | 1032 net_log_); |
| 1026 } | 1033 } |
| 1027 | 1034 |
| 1028 int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) { | 1035 int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) { |
| 1029 verifier_.reset(); | 1036 verifier_.reset(); |
| 1030 | 1037 |
| 1031 if (result == OK) { | 1038 if (result == OK) { |
| 1032 // TODO(joth): Work out if we need to remember the intermediate CA certs | 1039 // TODO(joth): Work out if we need to remember the intermediate CA certs |
| 1033 // when the server sends them to us, and do so here. | 1040 // when the server sends them to us, and do so here. |
| 1034 SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_); | 1041 SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_); |
| 1042 marked_session_as_good_ = true; | |
| 1043 CheckIfHandshakeFinished(); | |
| 1035 } else { | 1044 } else { |
| 1036 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) | 1045 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) |
| 1037 << " (" << result << ")"; | 1046 << " (" << result << ")"; |
| 1038 } | 1047 } |
| 1039 | 1048 |
| 1040 completed_handshake_ = true; | 1049 completed_handshake_ = true; |
| 1041 // Exit DoHandshakeLoop and return the result to the caller to Connect. | 1050 // Exit DoHandshakeLoop and return the result to the caller to Connect. |
| 1042 DCHECK_EQ(STATE_NONE, next_handshake_state_); | 1051 DCHECK_EQ(STATE_NONE, next_handshake_state_); |
| 1043 return result; | 1052 return result; |
| 1044 } | 1053 } |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1570 // write payload. If the current payload fails to write, the error will be | 1579 // write payload. If the current payload fails to write, the error will be |
| 1571 // reported in a future write or read to |bio|. | 1580 // reported in a future write or read to |bio|. |
| 1572 if (transport_write_error_ != OK) { | 1581 if (transport_write_error_ != OK) { |
| 1573 OpenSSLPutNetError(FROM_HERE, transport_write_error_); | 1582 OpenSSLPutNetError(FROM_HERE, transport_write_error_); |
| 1574 return -1; | 1583 return -1; |
| 1575 } | 1584 } |
| 1576 } | 1585 } |
| 1577 return retvalue; | 1586 return retvalue; |
| 1578 } | 1587 } |
| 1579 | 1588 |
| 1589 // Determines if the session for |ssl_| is in the cache, and calls the | |
|
wtc
2014/08/07 20:04:03
"the session for |ssl_| is in the cache" is not tr
| |
| 1590 // handshake completion callback if that is the case. | |
| 1591 // | |
| 1592 // CheckIfHandshakeFinished is called twice per connection: once after | |
| 1593 // MarkSSLSessionAsGood, when the certificate has been verified, and | |
| 1594 // once via an OpenSSL callback when the handshake has completed. On the | |
| 1595 // second call, when the certificate has been verified and the handshake | |
| 1596 // has completed, the connection's handshake completion callback is run. | |
| 1597 void SSLClientSocketOpenSSL::CheckIfHandshakeFinished() { | |
|
wtc
2014/08/07 20:04:03
Nit: to match the declaration order in the .h file
| |
| 1598 if (ran_handshake_finished_callback_ && marked_session_as_good_) | |
| 1599 OnHandshakeCompletion(); | |
| 1600 } | |
| 1601 | |
| 1580 // static | 1602 // static |
| 1581 long SSLClientSocketOpenSSL::BIOCallback( | 1603 long SSLClientSocketOpenSSL::BIOCallback( |
| 1582 BIO *bio, | 1604 BIO *bio, |
| 1583 int cmd, | 1605 int cmd, |
| 1584 const char *argp, int argi, long argl, | 1606 const char *argp, int argi, long argl, |
| 1585 long retvalue) { | 1607 long retvalue) { |
| 1586 SSLClientSocketOpenSSL* socket = reinterpret_cast<SSLClientSocketOpenSSL*>( | 1608 SSLClientSocketOpenSSL* socket = reinterpret_cast<SSLClientSocketOpenSSL*>( |
| 1587 BIO_get_callback_arg(bio)); | 1609 BIO_get_callback_arg(bio)); |
| 1588 CHECK(socket); | 1610 CHECK(socket); |
| 1589 return socket->MaybeReplayTransportError( | 1611 return socket->MaybeReplayTransportError( |
| 1590 bio, cmd, argp, argi, argl, retvalue); | 1612 bio, cmd, argp, argi, argl, retvalue); |
| 1591 } | 1613 } |
| 1592 | 1614 |
| 1593 scoped_refptr<X509Certificate> | 1615 scoped_refptr<X509Certificate> |
| 1594 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { | 1616 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { |
| 1595 return server_cert_; | 1617 return server_cert_; |
| 1596 } | 1618 } |
| 1597 | 1619 |
| 1598 } // namespace net | 1620 } // namespace net |
| OLD | NEW |