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 void SSLClientSocketOpenSSL::SetSSLHandshakeComplete() { |
| 682 ran_session_finished_callback_ = true; |
| 683 } |
| 684 |
| 685 // static |
| 686 void SSLClientSocketOpenSSL::OnSessionFinishedCallback(const SSL* ssl, |
| 687 int result, |
| 688 int unused) { |
| 689 SSLClientSocketOpenSSL* ssl_socket = |
| 690 SSLContext::GetInstance()->GetClientSocketFromSSL(ssl); |
| 691 if (result == SSL_CB_HANDSHAKE_DONE) { |
| 692 ssl_socket->SetSSLHandshakeComplete(); |
| 693 ssl_socket->CheckIfSessionFinished(); |
| 694 } |
| 695 } |
| 696 |
690 int SSLClientSocketOpenSSL::Init() { | 697 int SSLClientSocketOpenSSL::Init() { |
691 DCHECK(!ssl_); | 698 DCHECK(!ssl_); |
692 DCHECK(!transport_bio_); | 699 DCHECK(!transport_bio_); |
693 | 700 |
694 SSLContext* context = SSLContext::GetInstance(); | 701 SSLContext* context = SSLContext::GetInstance(); |
695 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 702 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
696 | 703 |
697 ssl_ = SSL_new(context->ssl_ctx()); | 704 ssl_ = SSL_new(context->ssl_ctx()); |
698 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) | 705 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) |
699 return ERR_UNEXPECTED; | 706 return ERR_UNEXPECTED; |
700 | 707 |
701 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) | 708 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) |
702 return ERR_UNEXPECTED; | 709 return ERR_UNEXPECTED; |
703 | 710 |
| 711 // Set an OpenSSL callback to monitor this SSL*'s connection. |
| 712 SSL_set_info_callback(ssl_, &OnSessionFinishedCallback); |
| 713 |
704 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( | 714 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( |
705 ssl_, GetSessionCacheKey()); | 715 ssl_, GetSessionCacheKey()); |
706 | 716 |
707 BIO* ssl_bio = NULL; | 717 BIO* ssl_bio = NULL; |
708 // 0 => use default buffer sizes. | 718 // 0 => use default buffer sizes. |
709 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 719 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
710 return ERR_UNEXPECTED; | 720 return ERR_UNEXPECTED; |
711 DCHECK(ssl_bio); | 721 DCHECK(ssl_bio); |
712 DCHECK(transport_bio_); | 722 DCHECK(transport_bio_); |
713 | 723 |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 net_log_); | 1035 net_log_); |
1026 } | 1036 } |
1027 | 1037 |
1028 int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) { | 1038 int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) { |
1029 verifier_.reset(); | 1039 verifier_.reset(); |
1030 | 1040 |
1031 if (result == OK) { | 1041 if (result == OK) { |
1032 // TODO(joth): Work out if we need to remember the intermediate CA certs | 1042 // 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. | 1043 // when the server sends them to us, and do so here. |
1034 SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_); | 1044 SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_); |
| 1045 CheckIfSessionFinished(); |
1035 } else { | 1046 } else { |
1036 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) | 1047 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) |
1037 << " (" << result << ")"; | 1048 << " (" << result << ")"; |
1038 } | 1049 } |
1039 | 1050 |
1040 completed_handshake_ = true; | 1051 completed_handshake_ = true; |
1041 // Exit DoHandshakeLoop and return the result to the caller to Connect. | 1052 // Exit DoHandshakeLoop and return the result to the caller to Connect. |
1042 DCHECK_EQ(STATE_NONE, next_handshake_state_); | 1053 DCHECK_EQ(STATE_NONE, next_handshake_state_); |
1043 return result; | 1054 return result; |
1044 } | 1055 } |
(...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 | 1581 // write payload. If the current payload fails to write, the error will be |
1571 // reported in a future write or read to |bio|. | 1582 // reported in a future write or read to |bio|. |
1572 if (transport_write_error_ != OK) { | 1583 if (transport_write_error_ != OK) { |
1573 OpenSSLPutNetError(FROM_HERE, transport_write_error_); | 1584 OpenSSLPutNetError(FROM_HERE, transport_write_error_); |
1574 return -1; | 1585 return -1; |
1575 } | 1586 } |
1576 } | 1587 } |
1577 return retvalue; | 1588 return retvalue; |
1578 } | 1589 } |
1579 | 1590 |
| 1591 // Determines if the session for |ssl| is in the cache, and calls the |
| 1592 // appropriate callback if that is the case. |
| 1593 // |
| 1594 // CheckIfSessionFinished is called twice per connection: once after |
| 1595 // MarkSSLSessionAsGood, when the certificate has been verified, and |
| 1596 // once via an OpenSSL callback when the handshake has completed. On the |
| 1597 // second call, when the certificate has been verified and the handshake |
| 1598 // has completed, the connection's handshake completion callback is run. |
| 1599 void SSLClientSocketOpenSSL::CheckIfSessionFinished() { |
| 1600 if (ran_session_finished_callback_ && |
| 1601 SSLContext::GetInstance()->session_cache()->SessionIsGood(ssl_)) { |
| 1602 OnHandshakeCompletion(); |
| 1603 } |
| 1604 } |
| 1605 |
1580 // static | 1606 // static |
1581 long SSLClientSocketOpenSSL::BIOCallback( | 1607 long SSLClientSocketOpenSSL::BIOCallback( |
1582 BIO *bio, | 1608 BIO *bio, |
1583 int cmd, | 1609 int cmd, |
1584 const char *argp, int argi, long argl, | 1610 const char *argp, int argi, long argl, |
1585 long retvalue) { | 1611 long retvalue) { |
1586 SSLClientSocketOpenSSL* socket = reinterpret_cast<SSLClientSocketOpenSSL*>( | 1612 SSLClientSocketOpenSSL* socket = reinterpret_cast<SSLClientSocketOpenSSL*>( |
1587 BIO_get_callback_arg(bio)); | 1613 BIO_get_callback_arg(bio)); |
1588 CHECK(socket); | 1614 CHECK(socket); |
1589 return socket->MaybeReplayTransportError( | 1615 return socket->MaybeReplayTransportError( |
1590 bio, cmd, argp, argi, argl, retvalue); | 1616 bio, cmd, argp, argi, argl, retvalue); |
1591 } | 1617 } |
1592 | 1618 |
1593 scoped_refptr<X509Certificate> | 1619 scoped_refptr<X509Certificate> |
1594 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { | 1620 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { |
1595 return server_cert_; | 1621 return server_cert_; |
1596 } | 1622 } |
1597 | 1623 |
1598 } // namespace net | 1624 } // namespace net |
OLD | NEW |