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 |