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 |