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 struct SSLContextSingletonTraits : public DefaultSingletonTraits<SSL_CTX> { |
| 69 static SSL_CTX* New() { |
| 70 base::EnsureOpenSSLInit(); |
| 71 SSL_CTX* self = SSL_CTX_new(SSLv23_client_method()); |
| 72 SSL_CTX_set_cert_verify_callback(self, NoOpVerifyCallback, NULL); |
| 73 return self; |
| 74 } |
| 75 static void Delete(SSL_CTX* self) { |
| 76 SSL_CTX_free(self); |
| 77 } |
| 78 }; |
| 79 |
| 80 SSL_CTX* GetSSLContext() { |
| 81 return Singleton<SSL_CTX, SSLContextSingletonTraits>::get(); |
| 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 ssl_ = SSL_new(GetSSLContext()); |
97 if (!ssl_) { | 120 if (!ssl_) { |
98 MaybeLogSSLError(); | 121 MaybeLogSSLError(); |
99 return false; | 122 return false; |
100 } | 123 } |
101 | 124 |
102 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) { | 125 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) { |
103 MaybeLogSSLError(); | 126 MaybeLogSSLError(); |
104 return false; | 127 return false; |
105 } | 128 } |
106 | 129 |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 } | 410 } |
388 | 411 |
389 void SSLClientSocketOpenSSL::InvalidateSessionIfBadCertificate() { | 412 void SSLClientSocketOpenSSL::InvalidateSessionIfBadCertificate() { |
390 if (UpdateServerCert() != NULL && | 413 if (UpdateServerCert() != NULL && |
391 ssl_config_.IsAllowedBadCert(server_cert_)) { | 414 ssl_config_.IsAllowedBadCert(server_cert_)) { |
392 // Remove from session cache but don't clear this connection. | 415 // Remove from session cache but don't clear this connection. |
393 // TODO(joth): This should be a no-op until we enable session caching, | 416 // 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). | 417 // see SSL_CTX_set_session_cache_mode(SSL_SESS_CACHE_CLIENT). |
395 SSL_SESSION* session = SSL_get_session(ssl_); | 418 SSL_SESSION* session = SSL_get_session(ssl_); |
396 LOG_IF(ERROR, session) << "Connection has a session?? " << session; | 419 LOG_IF(ERROR, session) << "Connection has a session?? " << session; |
397 int rv = SSL_CTX_remove_session(GetOpenSSLInitSingleton()->ssl_ctx(), | 420 int rv = SSL_CTX_remove_session(GetSSLContext(), session); |
398 session); | |
399 LOG_IF(ERROR, rv) << "Session was cached?? " << rv; | 421 LOG_IF(ERROR, rv) << "Session was cached?? " << rv; |
400 } | 422 } |
401 } | 423 } |
402 | 424 |
403 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { | 425 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { |
404 if (server_cert_) | 426 if (server_cert_) |
405 return server_cert_; | 427 return server_cert_; |
406 | 428 |
407 ScopedSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); | 429 base::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); |
408 if (!cert.get()) { | 430 if (!cert.get()) { |
409 LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; | 431 LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; |
410 return NULL; | 432 return NULL; |
411 } | 433 } |
412 | 434 |
413 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not | 435 // 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. | 436 // increment the reference so sk_X509_free does not need to be called. |
415 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); | 437 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); |
416 X509Certificate::OSCertHandles intermediates; | 438 X509Certificate::OSCertHandles intermediates; |
417 if (chain) { | 439 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_); | 753 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
732 | 754 |
733 if (rv >= 0) | 755 if (rv >= 0) |
734 return rv; | 756 return rv; |
735 | 757 |
736 int err = SSL_get_error(ssl_, rv); | 758 int err = SSL_get_error(ssl_, rv); |
737 return MapOpenSSLError(err); | 759 return MapOpenSSLError(err); |
738 } | 760 } |
739 | 761 |
740 } // namespace net | 762 } // namespace net |
OLD | NEW |