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_session_finished_callback_(false), | |
| 366 net_log_(transport_->socket()->NetLog()) { | 367 net_log_(transport_->socket()->NetLog()) { |
| 367 } | 368 } |
| 368 | 369 |
| 369 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | 370 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { |
| 370 Disconnect(); | 371 Disconnect(); |
| 371 } | 372 } |
| 372 | 373 |
| 373 bool SSLClientSocketOpenSSL::InSessionCache() const { | 374 bool SSLClientSocketOpenSSL::InSessionCache() const { |
| 374 SSLContext* context = SSLContext::GetInstance(); | 375 SSLContext* context = SSLContext::GetInstance(); |
| 375 std::string cache_key = GetSessionCacheKey(); | 376 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) { | 429 int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) { |
| 429 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT); | 430 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT); |
| 430 | 431 |
| 431 // Set up new ssl object. | 432 // Set up new ssl object. |
| 432 int rv = Init(); | 433 int rv = Init(); |
| 433 if (rv != OK) { | 434 if (rv != OK) { |
| 434 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 435 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
| 435 return rv; | 436 return rv; |
| 436 } | 437 } |
| 437 | 438 |
| 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. | 439 // Set SSL to client mode. Handshake happens in the loop below. |
| 447 SSL_set_connect_state(ssl_); | 440 SSL_set_connect_state(ssl_); |
| 448 | 441 |
| 449 GotoState(STATE_HANDSHAKE); | 442 GotoState(STATE_HANDSHAKE); |
| 450 rv = DoHandshakeLoop(OK); | 443 rv = DoHandshakeLoop(OK); |
| 451 if (rv == ERR_IO_PENDING) { | 444 if (rv == ERR_IO_PENDING) { |
| 452 user_connect_callback_ = callback; | 445 user_connect_callback_ = callback; |
| 453 } else { | 446 } else { |
| 454 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 447 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
| 455 if (rv < OK) | 448 if (rv < OK) |
| 456 OnHandshakeCompletion(); | 449 OnHandshakeCompletion(); |
| 457 } | 450 } |
| 458 | 451 |
| 459 return rv > OK ? OK : rv; | 452 return rv > OK ? OK : rv; |
| 460 } | 453 } |
| 461 | 454 |
| 462 void SSLClientSocketOpenSSL::Disconnect() { | 455 void SSLClientSocketOpenSSL::Disconnect() { |
| 463 // If a handshake was pending (Connect() had been called), notify interested | 456 // If a handshake was pending (Connect() had been called), notify interested |
| 464 // parties that it's been aborted now. If the handshake had already | 457 // parties that it's been aborted now. If the handshake had already |
| 465 // completed, this is a no-op. | 458 // completed, this is a no-op. |
| 466 OnHandshakeCompletion(); | 459 OnHandshakeCompletion(); |
| 467 if (ssl_) { | 460 if (ssl_) { |
| 468 SSLContext* context = SSLContext::GetInstance(); | |
| 469 context->session_cache()->RemoveSessionAddedCallback(ssl_); | |
| 470 // Calling SSL_shutdown prevents the session from being marked as | 461 // Calling SSL_shutdown prevents the session from being marked as |
| 471 // unresumable. | 462 // unresumable. |
| 472 SSL_shutdown(ssl_); | 463 SSL_shutdown(ssl_); |
| 473 SSL_free(ssl_); | 464 SSL_free(ssl_); |
| 474 ssl_ = NULL; | 465 ssl_ = NULL; |
| 475 } | 466 } |
| 476 if (transport_bio_) { | 467 if (transport_bio_) { |
| 477 BIO_free_all(transport_bio_); | 468 BIO_free_all(transport_bio_); |
| 478 transport_bio_ = NULL; | 469 transport_bio_ = NULL; |
| 479 } | 470 } |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 680 } | 671 } |
| 681 | 672 |
| 682 int SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { | 673 int SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { |
| 683 return transport_->socket()->SetReceiveBufferSize(size); | 674 return transport_->socket()->SetReceiveBufferSize(size); |
| 684 } | 675 } |
| 685 | 676 |
| 686 int SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { | 677 int SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { |
| 687 return transport_->socket()->SetSendBufferSize(size); | 678 return transport_->socket()->SetSendBufferSize(size); |
| 688 } | 679 } |
| 689 | 680 |
| 681 // static | |
| 682 void SSLClientSocketOpenSSL::OnSessionFinishedCallback(const SSL* ssl, | |
| 683 int result, | |
| 684 int unused) { | |
|
wtc
2014/08/07 02:10:12
The Style Guide recommends commenting out the name
| |
| 685 SSLClientSocketOpenSSL* ssl_socket = | |
| 686 SSLContext::GetInstance()->GetClientSocketFromSSL(ssl); | |
| 687 if (result == SSL_CB_HANDSHAKE_DONE) { | |
| 688 ssl_socket->ran_session_finished_callback_ = true; | |
| 689 ssl_socket->CheckIfSessionFinished(); | |
| 690 } | |
| 691 } | |
| 692 | |
| 690 int SSLClientSocketOpenSSL::Init() { | 693 int SSLClientSocketOpenSSL::Init() { |
| 691 DCHECK(!ssl_); | 694 DCHECK(!ssl_); |
| 692 DCHECK(!transport_bio_); | 695 DCHECK(!transport_bio_); |
| 693 | 696 |
| 694 SSLContext* context = SSLContext::GetInstance(); | 697 SSLContext* context = SSLContext::GetInstance(); |
| 695 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 698 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 696 | 699 |
| 697 ssl_ = SSL_new(context->ssl_ctx()); | 700 ssl_ = SSL_new(context->ssl_ctx()); |
| 698 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) | 701 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) |
| 699 return ERR_UNEXPECTED; | 702 return ERR_UNEXPECTED; |
| 700 | 703 |
| 701 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) | 704 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) |
| 702 return ERR_UNEXPECTED; | 705 return ERR_UNEXPECTED; |
| 703 | 706 |
| 707 // Set an OpenSSL callback to monitor this SSL*'s connection. | |
| 708 SSL_set_info_callback(ssl_, &OnSessionFinishedCallback); | |
| 709 | |
| 704 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( | 710 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( |
| 705 ssl_, GetSessionCacheKey()); | 711 ssl_, GetSessionCacheKey()); |
| 706 | 712 |
| 707 BIO* ssl_bio = NULL; | 713 BIO* ssl_bio = NULL; |
| 708 // 0 => use default buffer sizes. | 714 // 0 => use default buffer sizes. |
| 709 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 715 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
| 710 return ERR_UNEXPECTED; | 716 return ERR_UNEXPECTED; |
| 711 DCHECK(ssl_bio); | 717 DCHECK(ssl_bio); |
| 712 DCHECK(transport_bio_); | 718 DCHECK(transport_bio_); |
| 713 | 719 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1025 net_log_); | 1031 net_log_); |
| 1026 } | 1032 } |
| 1027 | 1033 |
| 1028 int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) { | 1034 int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) { |
| 1029 verifier_.reset(); | 1035 verifier_.reset(); |
| 1030 | 1036 |
| 1031 if (result == OK) { | 1037 if (result == OK) { |
| 1032 // TODO(joth): Work out if we need to remember the intermediate CA certs | 1038 // 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. | 1039 // when the server sends them to us, and do so here. |
| 1034 SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_); | 1040 SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_); |
| 1041 CheckIfSessionFinished(); | |
| 1035 } else { | 1042 } else { |
| 1036 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) | 1043 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) |
| 1037 << " (" << result << ")"; | 1044 << " (" << result << ")"; |
| 1038 } | 1045 } |
| 1039 | 1046 |
| 1040 completed_handshake_ = true; | 1047 completed_handshake_ = true; |
| 1041 // Exit DoHandshakeLoop and return the result to the caller to Connect. | 1048 // Exit DoHandshakeLoop and return the result to the caller to Connect. |
| 1042 DCHECK_EQ(STATE_NONE, next_handshake_state_); | 1049 DCHECK_EQ(STATE_NONE, next_handshake_state_); |
| 1043 return result; | 1050 return result; |
| 1044 } | 1051 } |
| (...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 | 1577 // write payload. If the current payload fails to write, the error will be |
| 1571 // reported in a future write or read to |bio|. | 1578 // reported in a future write or read to |bio|. |
| 1572 if (transport_write_error_ != OK) { | 1579 if (transport_write_error_ != OK) { |
| 1573 OpenSSLPutNetError(FROM_HERE, transport_write_error_); | 1580 OpenSSLPutNetError(FROM_HERE, transport_write_error_); |
| 1574 return -1; | 1581 return -1; |
| 1575 } | 1582 } |
| 1576 } | 1583 } |
| 1577 return retvalue; | 1584 return retvalue; |
| 1578 } | 1585 } |
| 1579 | 1586 |
| 1587 // Determines if the session for |ssl| is in the cache, and calls the | |
|
wtc
2014/08/07 02:10:12
|ssl| => |ssl_|
| |
| 1588 // appropriate callback if that is the case. | |
|
wtc
2014/08/07 02:10:12
Nit: be more specific than "the appropriate callba
| |
| 1589 // | |
| 1590 // CheckIfSessionFinished is called twice per connection: once after | |
| 1591 // MarkSSLSessionAsGood, when the certificate has been verified, and | |
| 1592 // once via an OpenSSL callback when the handshake has completed. On the | |
| 1593 // second call, when the certificate has been verified and the handshake | |
| 1594 // has completed, the connection's handshake completion callback is run. | |
| 1595 void SSLClientSocketOpenSSL::CheckIfSessionFinished() { | |
|
wtc
2014/08/07 02:10:12
This method should be renamed, but I don't have a
| |
| 1596 if (ran_session_finished_callback_ && | |
| 1597 SSLContext::GetInstance()->session_cache()->SessionIsGood(ssl_)) { | |
|
wtc
2014/08/07 02:10:12
IMPORTANT: It seems that we are doing this the har
| |
| 1598 OnHandshakeCompletion(); | |
| 1599 } | |
| 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 |