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 |