Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: net/socket/ssl_client_socket_openssl.cc

Issue 416683002: This CL corrects a bug in which the OnHandshakeComplete callback for an ssl session was never called (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@r2
Patch Set: Changed the names of several confusingly named methods. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698