Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 <openssl/ssl.h> | 10 #include <openssl/ssl.h> |
| 11 #include <openssl/err.h> | 11 #include <openssl/err.h> |
| 12 | 12 |
| 13 #include "base/metrics/histogram.h" | |
| 14 #include "base/openssl_util.h" | |
| 13 #include "net/base/cert_verifier.h" | 15 #include "net/base/cert_verifier.h" |
| 14 #include "base/metrics/histogram.h" | |
| 15 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 16 #include "net/base/openssl_util.h" | |
| 17 #include "net/base/ssl_connection_status_flags.h" | 17 #include "net/base/ssl_connection_status_flags.h" |
| 18 #include "net/base/ssl_info.h" | 18 #include "net/base/ssl_info.h" |
| 19 | 19 |
| 20 namespace net { | 20 namespace net { |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 // Enable this to see logging for state machine state transitions. | 24 // Enable this to see logging for state machine state transitions. |
| 25 #if 0 | 25 #if 0 |
| 26 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ | 26 #define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 51 MaybeLogSSLError(); | 51 MaybeLogSSLError(); |
| 52 return ERR_SSL_PROTOCOL_ERROR; | 52 return ERR_SSL_PROTOCOL_ERROR; |
| 53 default: | 53 default: |
| 54 // TODO(joth): Implement full mapping. | 54 // TODO(joth): Implement full mapping. |
| 55 LOG(WARNING) << "Unknown OpenSSL error " << err; | 55 LOG(WARNING) << "Unknown OpenSSL error " << err; |
| 56 MaybeLogSSLError(); | 56 MaybeLogSSLError(); |
| 57 return ERR_SSL_PROTOCOL_ERROR; | 57 return ERR_SSL_PROTOCOL_ERROR; |
| 58 } | 58 } |
| 59 } | 59 } |
| 60 | 60 |
| 61 // We do certificate verification after handshake, so we disable the default | |
| 62 // by registering a no-op verify function. | |
| 63 int NoOpVerifyCallback(X509_STORE_CTX*, void *) { | |
| 64 DVLOG(3) << "skipping cert verify"; | |
| 65 return 1; | |
| 66 } | |
| 67 | |
| 68 class OpenSSLContext { | |
| 69 public: | |
| 70 SSL_CTX* ssl_ctx() const { return ssl_ctx_.get(); } | |
| 71 | |
| 72 private: | |
| 73 friend struct DefaultSingletonTraits<OpenSSLContext>; | |
| 74 OpenSSLContext() | |
| 75 : ssl_ctx_(SSL_CTX_new(SSLv23_client_method())) { | |
|
bulach
2010/11/16 14:23:50
see below, perhaps move out of the initializer lis
joth
2010/11/16 15:57:41
Done.
ScopedSSL makes this a little more complex.
| |
| 76 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | |
| 77 } | |
| 78 | |
| 79 base::ScopedSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | |
| 80 | |
| 81 DISALLOW_COPY_AND_ASSIGN(OpenSSLContext); | |
| 82 }; | |
| 83 | |
| 61 } // namespace | 84 } // namespace |
| 62 | 85 |
| 63 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( | 86 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( |
| 64 ClientSocketHandle* transport_socket, | 87 ClientSocketHandle* transport_socket, |
| 65 const HostPortPair& host_and_port, | 88 const HostPortPair& host_and_port, |
| 66 const SSLConfig& ssl_config) | 89 const SSLConfig& ssl_config) |
| 67 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( | 90 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( |
| 68 this, &SSLClientSocketOpenSSL::BufferSendComplete)), | 91 this, &SSLClientSocketOpenSSL::BufferSendComplete)), |
| 69 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_( | 92 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_( |
| 70 this, &SSLClientSocketOpenSSL::BufferRecvComplete)), | 93 this, &SSLClientSocketOpenSSL::BufferRecvComplete)), |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 86 } | 109 } |
| 87 | 110 |
| 88 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | 111 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { |
| 89 Disconnect(); | 112 Disconnect(); |
| 90 } | 113 } |
| 91 | 114 |
| 92 bool SSLClientSocketOpenSSL::Init() { | 115 bool SSLClientSocketOpenSSL::Init() { |
| 93 DCHECK(!ssl_); | 116 DCHECK(!ssl_); |
| 94 DCHECK(!transport_bio_); | 117 DCHECK(!transport_bio_); |
| 95 | 118 |
| 96 ssl_ = SSL_new(GetOpenSSLInitSingleton()->ssl_ctx()); | 119 base::EnsureOpenSSLInit(); |
|
bulach
2010/11/16 14:23:50
it'd be better to move this to OpenSSLContext's ct
joth
2010/11/16 15:57:41
Done.
| |
| 120 ssl_ = SSL_new(Singleton<OpenSSLContext>::get()->ssl_ctx()); | |
| 97 if (!ssl_) { | 121 if (!ssl_) { |
| 98 MaybeLogSSLError(); | 122 MaybeLogSSLError(); |
| 99 return false; | 123 return false; |
| 100 } | 124 } |
| 101 | 125 |
| 102 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) { | 126 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) { |
| 103 MaybeLogSSLError(); | 127 MaybeLogSSLError(); |
| 104 return false; | 128 return false; |
| 105 } | 129 } |
| 106 | 130 |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 } | 411 } |
| 388 | 412 |
| 389 void SSLClientSocketOpenSSL::InvalidateSessionIfBadCertificate() { | 413 void SSLClientSocketOpenSSL::InvalidateSessionIfBadCertificate() { |
| 390 if (UpdateServerCert() != NULL && | 414 if (UpdateServerCert() != NULL && |
| 391 ssl_config_.IsAllowedBadCert(server_cert_)) { | 415 ssl_config_.IsAllowedBadCert(server_cert_)) { |
| 392 // Remove from session cache but don't clear this connection. | 416 // Remove from session cache but don't clear this connection. |
| 393 // TODO(joth): This should be a no-op until we enable session caching, | 417 // TODO(joth): This should be a no-op until we enable session caching, |
| 394 // see SSL_CTX_set_session_cache_mode(SSL_SESS_CACHE_CLIENT). | 418 // see SSL_CTX_set_session_cache_mode(SSL_SESS_CACHE_CLIENT). |
| 395 SSL_SESSION* session = SSL_get_session(ssl_); | 419 SSL_SESSION* session = SSL_get_session(ssl_); |
| 396 LOG_IF(ERROR, session) << "Connection has a session?? " << session; | 420 LOG_IF(ERROR, session) << "Connection has a session?? " << session; |
| 397 int rv = SSL_CTX_remove_session(GetOpenSSLInitSingleton()->ssl_ctx(), | 421 int rv = SSL_CTX_remove_session(Singleton<OpenSSLContext>::get()->ssl_ctx(), |
| 398 session); | 422 session); |
| 399 LOG_IF(ERROR, rv) << "Session was cached?? " << rv; | 423 LOG_IF(ERROR, rv) << "Session was cached?? " << rv; |
| 400 } | 424 } |
| 401 } | 425 } |
| 402 | 426 |
| 403 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { | 427 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { |
| 404 if (server_cert_) | 428 if (server_cert_) |
| 405 return server_cert_; | 429 return server_cert_; |
| 406 | 430 |
| 407 ScopedSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); | 431 base::ScopedSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); |
| 408 if (!cert.get()) { | 432 if (!cert.get()) { |
| 409 LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; | 433 LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; |
| 410 return NULL; | 434 return NULL; |
| 411 } | 435 } |
| 412 | 436 |
| 413 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not | 437 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not |
| 414 // increment the reference so sk_X509_free does not need to be called. | 438 // increment the reference so sk_X509_free does not need to be called. |
| 415 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); | 439 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); |
| 416 X509Certificate::OSCertHandles intermediates; | 440 X509Certificate::OSCertHandles intermediates; |
| 417 if (chain) { | 441 if (chain) { |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 731 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | 755 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
| 732 | 756 |
| 733 if (rv >= 0) | 757 if (rv >= 0) |
| 734 return rv; | 758 return rv; |
| 735 | 759 |
| 736 int err = SSL_get_error(ssl_, rv); | 760 int err = SSL_get_error(ssl_, rv); |
| 737 return MapOpenSSLError(err); | 761 return MapOpenSSLError(err); |
| 738 } | 762 } |
| 739 | 763 |
| 740 } // namespace net | 764 } // namespace net |
| OLD | NEW |