OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/memory/singleton.h" | 13 #include "base/memory/singleton.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/openssl_util.h" | |
16 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
| 16 #include "crypto/openssl_util.h" |
17 #include "net/base/cert_verifier.h" | 17 #include "net/base/cert_verifier.h" |
18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
19 #include "net/base/openssl_private_key_store.h" | 19 #include "net/base/openssl_private_key_store.h" |
20 #include "net/base/ssl_cert_request_info.h" | 20 #include "net/base/ssl_cert_request_info.h" |
21 #include "net/base/ssl_connection_status_flags.h" | 21 #include "net/base/ssl_connection_status_flags.h" |
22 #include "net/base/ssl_info.h" | 22 #include "net/base/ssl_info.h" |
23 #include "net/socket/ssl_error_params.h" | 23 #include "net/socket/ssl_error_params.h" |
24 | 24 |
25 namespace net { | 25 namespace net { |
26 | 26 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 default: | 165 default: |
166 LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code); | 166 LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code); |
167 return ERR_FAILED; | 167 return ERR_FAILED; |
168 } | 168 } |
169 } | 169 } |
170 | 170 |
171 // Converts an OpenSSL error code into a net error code, walking the OpenSSL | 171 // Converts an OpenSSL error code into a net error code, walking the OpenSSL |
172 // error stack if needed. Note that |tracer| is not currently used in the | 172 // error stack if needed. Note that |tracer| is not currently used in the |
173 // implementation, but is passed in anyway as this ensures the caller will clear | 173 // implementation, but is passed in anyway as this ensures the caller will clear |
174 // any residual codes left on the error stack. | 174 // any residual codes left on the error stack. |
175 int MapOpenSSLError(int err, const base::OpenSSLErrStackTracer& tracer) { | 175 int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) { |
176 switch (err) { | 176 switch (err) { |
177 case SSL_ERROR_WANT_READ: | 177 case SSL_ERROR_WANT_READ: |
178 case SSL_ERROR_WANT_WRITE: | 178 case SSL_ERROR_WANT_WRITE: |
179 return ERR_IO_PENDING; | 179 return ERR_IO_PENDING; |
180 case SSL_ERROR_SYSCALL: | 180 case SSL_ERROR_SYSCALL: |
181 DVLOG(1) << "OpenSSL SYSCALL error, errno " << errno; | 181 DVLOG(1) << "OpenSSL SYSCALL error, errno " << errno; |
182 return ERR_SSL_PROTOCOL_ERROR; | 182 return ERR_SSL_PROTOCOL_ERROR; |
183 case SSL_ERROR_SSL: | 183 case SSL_ERROR_SSL: |
184 return MapOpenSSLErrorSSL(); | 184 return MapOpenSSLErrorSSL(); |
185 default: | 185 default: |
(...skipping 13 matching lines...) Expand all Loading... |
199 // OpenSSL manages a cache of SSL_SESSION, this class provides the application | 199 // OpenSSL manages a cache of SSL_SESSION, this class provides the application |
200 // side policy for that cache about session re-use: we retain one session per | 200 // side policy for that cache about session re-use: we retain one session per |
201 // unique HostPortPair. | 201 // unique HostPortPair. |
202 class SSLSessionCache { | 202 class SSLSessionCache { |
203 public: | 203 public: |
204 SSLSessionCache() {} | 204 SSLSessionCache() {} |
205 | 205 |
206 void OnSessionAdded(const HostPortPair& host_and_port, SSL_SESSION* session) { | 206 void OnSessionAdded(const HostPortPair& host_and_port, SSL_SESSION* session) { |
207 // Declare the session cleaner-upper before the lock, so any call into | 207 // Declare the session cleaner-upper before the lock, so any call into |
208 // OpenSSL to free the session will happen after the lock is released. | 208 // OpenSSL to free the session will happen after the lock is released. |
209 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; | 209 crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; |
210 base::AutoLock lock(lock_); | 210 base::AutoLock lock(lock_); |
211 | 211 |
212 DCHECK_EQ(0U, session_map_.count(session)); | 212 DCHECK_EQ(0U, session_map_.count(session)); |
213 std::pair<HostPortMap::iterator, bool> res = | 213 std::pair<HostPortMap::iterator, bool> res = |
214 host_port_map_.insert(std::make_pair(host_and_port, session)); | 214 host_port_map_.insert(std::make_pair(host_and_port, session)); |
215 if (!res.second) { // Already exists: replace old entry. | 215 if (!res.second) { // Already exists: replace old entry. |
216 session_to_free.reset(res.first->second); | 216 session_to_free.reset(res.first->second); |
217 session_map_.erase(session_to_free.get()); | 217 session_map_.erase(session_to_free.get()); |
218 res.first->second = session; | 218 res.first->second = session; |
219 } | 219 } |
220 DVLOG(2) << "Adding session " << session << " => " | 220 DVLOG(2) << "Adding session " << session << " => " |
221 << host_and_port.ToString() << ", new entry = " << res.second; | 221 << host_and_port.ToString() << ", new entry = " << res.second; |
222 DCHECK(host_port_map_[host_and_port] == session); | 222 DCHECK(host_port_map_[host_and_port] == session); |
223 session_map_[session] = res.first; | 223 session_map_[session] = res.first; |
224 DCHECK_EQ(host_port_map_.size(), session_map_.size()); | 224 DCHECK_EQ(host_port_map_.size(), session_map_.size()); |
225 DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires); | 225 DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires); |
226 } | 226 } |
227 | 227 |
228 void OnSessionRemoved(SSL_SESSION* session) { | 228 void OnSessionRemoved(SSL_SESSION* session) { |
229 // Declare the session cleaner-upper before the lock, so any call into | 229 // Declare the session cleaner-upper before the lock, so any call into |
230 // OpenSSL to free the session will happen after the lock is released. | 230 // OpenSSL to free the session will happen after the lock is released. |
231 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; | 231 crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; |
232 base::AutoLock lock(lock_); | 232 base::AutoLock lock(lock_); |
233 | 233 |
234 SessionMap::iterator it = session_map_.find(session); | 234 SessionMap::iterator it = session_map_.find(session); |
235 if (it == session_map_.end()) | 235 if (it == session_map_.end()) |
236 return; | 236 return; |
237 DVLOG(2) << "Remove session " << session << " => " | 237 DVLOG(2) << "Remove session " << session << " => " |
238 << it->second->first.ToString(); | 238 << it->second->first.ToString(); |
239 DCHECK(it->second->second == session); | 239 DCHECK(it->second->second == session); |
240 host_port_map_.erase(it->second); | 240 host_port_map_.erase(it->second); |
241 session_map_.erase(it); | 241 session_map_.erase(it); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 } | 294 } |
295 | 295 |
296 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) { | 296 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) { |
297 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; | 297 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; |
298 } | 298 } |
299 | 299 |
300 private: | 300 private: |
301 friend struct DefaultSingletonTraits<SSLContext>; | 301 friend struct DefaultSingletonTraits<SSLContext>; |
302 | 302 |
303 SSLContext() { | 303 SSLContext() { |
304 base::EnsureOpenSSLInit(); | 304 crypto::EnsureOpenSSLInit(); |
305 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 305 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
306 DCHECK_NE(ssl_socket_data_index_, -1); | 306 DCHECK_NE(ssl_socket_data_index_, -1); |
307 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 307 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
308 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | 308 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); |
309 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); | 309 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); |
310 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); | 310 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); |
311 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); | 311 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); |
312 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); | 312 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); |
313 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); | 313 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); |
314 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); | 314 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 const unsigned char* in, | 351 const unsigned char* in, |
352 unsigned int inlen, void* arg) { | 352 unsigned int inlen, void* arg) { |
353 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 353 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
354 return socket->SelectNextProtoCallback(out, outlen, in, inlen); | 354 return socket->SelectNextProtoCallback(out, outlen, in, inlen); |
355 } | 355 } |
356 | 356 |
357 // This is the index used with SSL_get_ex_data to retrieve the owner | 357 // This is the index used with SSL_get_ex_data to retrieve the owner |
358 // SSLClientSocketOpenSSL object from an SSL instance. | 358 // SSLClientSocketOpenSSL object from an SSL instance. |
359 int ssl_socket_data_index_; | 359 int ssl_socket_data_index_; |
360 | 360 |
361 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | 361 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; |
362 SSLSessionCache session_cache_; | 362 SSLSessionCache session_cache_; |
363 }; | 363 }; |
364 | 364 |
365 // Utility to construct the appropriate set & clear masks for use the OpenSSL | 365 // Utility to construct the appropriate set & clear masks for use the OpenSSL |
366 // options and mode configuration functions. (SSL_set_options etc) | 366 // options and mode configuration functions. (SSL_set_options etc) |
367 struct SslSetClearMask { | 367 struct SslSetClearMask { |
368 SslSetClearMask() : set_mask(0), clear_mask(0) {} | 368 SslSetClearMask() : set_mask(0), clear_mask(0) {} |
369 void ConfigureFlag(long flag, bool state) { | 369 void ConfigureFlag(long flag, bool state) { |
370 (state ? set_mask : clear_mask) |= flag; | 370 (state ? set_mask : clear_mask) |= flag; |
371 // Make sure we haven't got any intersection in the set & clear options. | 371 // Make sure we haven't got any intersection in the set & clear options. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 | 408 |
409 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | 409 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { |
410 Disconnect(); | 410 Disconnect(); |
411 } | 411 } |
412 | 412 |
413 bool SSLClientSocketOpenSSL::Init() { | 413 bool SSLClientSocketOpenSSL::Init() { |
414 DCHECK(!ssl_); | 414 DCHECK(!ssl_); |
415 DCHECK(!transport_bio_); | 415 DCHECK(!transport_bio_); |
416 | 416 |
417 SSLContext* context = SSLContext::GetInstance(); | 417 SSLContext* context = SSLContext::GetInstance(); |
418 base::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 418 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
419 | 419 |
420 ssl_ = SSL_new(context->ssl_ctx()); | 420 ssl_ = SSL_new(context->ssl_ctx()); |
421 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) | 421 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) |
422 return false; | 422 return false; |
423 | 423 |
424 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) | 424 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) |
425 return false; | 425 return false; |
426 | 426 |
427 trying_cached_session_ = | 427 trying_cached_session_ = |
428 context->session_cache()->SetSSLSession(ssl_, host_and_port_); | 428 context->session_cache()->SetSSLSession(ssl_, host_and_port_); |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 break; | 716 break; |
717 | 717 |
718 // Do the actual network I/O. | 718 // Do the actual network I/O. |
719 network_moved = DoTransportIO(); | 719 network_moved = DoTransportIO(); |
720 } while ((rv != ERR_IO_PENDING || network_moved) && | 720 } while ((rv != ERR_IO_PENDING || network_moved) && |
721 next_handshake_state_ != STATE_NONE); | 721 next_handshake_state_ != STATE_NONE); |
722 return rv; | 722 return rv; |
723 } | 723 } |
724 | 724 |
725 int SSLClientSocketOpenSSL::DoHandshake() { | 725 int SSLClientSocketOpenSSL::DoHandshake() { |
726 base::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 726 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
727 int net_error = net::OK; | 727 int net_error = net::OK; |
728 int rv = SSL_do_handshake(ssl_); | 728 int rv = SSL_do_handshake(ssl_); |
729 | 729 |
730 if (client_auth_cert_needed_) { | 730 if (client_auth_cert_needed_) { |
731 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 731 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
732 // If the handshake already succeeded (because the server requests but | 732 // If the handshake already succeeded (because the server requests but |
733 // doesn't require a client cert), we need to invalidate the SSL session | 733 // doesn't require a client cert), we need to invalidate the SSL session |
734 // so that we won't try to resume the non-client-authenticated session in | 734 // so that we won't try to resume the non-client-authenticated session in |
735 // the next handshake. This will cause the server to ask for a client | 735 // the next handshake. This will cause the server to ask for a client |
736 // cert again. | 736 // cert again. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 completed_handshake_ = true; | 848 completed_handshake_ = true; |
849 // Exit DoHandshakeLoop and return the result to the caller to Connect. | 849 // Exit DoHandshakeLoop and return the result to the caller to Connect. |
850 DCHECK_EQ(STATE_NONE, next_handshake_state_); | 850 DCHECK_EQ(STATE_NONE, next_handshake_state_); |
851 return result; | 851 return result; |
852 } | 852 } |
853 | 853 |
854 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { | 854 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { |
855 if (server_cert_) | 855 if (server_cert_) |
856 return server_cert_; | 856 return server_cert_; |
857 | 857 |
858 base::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); | 858 crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); |
859 if (!cert.get()) { | 859 if (!cert.get()) { |
860 LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; | 860 LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; |
861 return NULL; | 861 return NULL; |
862 } | 862 } |
863 | 863 |
864 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not | 864 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not |
865 // increment the reference so sk_X509_free does not need to be called. | 865 // increment the reference so sk_X509_free does not need to be called. |
866 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); | 866 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); |
867 X509Certificate::OSCertHandles intermediates; | 867 X509Certificate::OSCertHandles intermediates; |
868 if (chain) { | 868 if (chain) { |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 | 1158 |
1159 bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { | 1159 bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { |
1160 return transport_->socket()->SetReceiveBufferSize(size); | 1160 return transport_->socket()->SetReceiveBufferSize(size); |
1161 } | 1161 } |
1162 | 1162 |
1163 bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { | 1163 bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { |
1164 return transport_->socket()->SetSendBufferSize(size); | 1164 return transport_->socket()->SetSendBufferSize(size); |
1165 } | 1165 } |
1166 | 1166 |
1167 int SSLClientSocketOpenSSL::DoPayloadRead() { | 1167 int SSLClientSocketOpenSSL::DoPayloadRead() { |
1168 base::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 1168 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
1169 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_); | 1169 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_); |
1170 // We don't need to invalidate the non-client-authenticated SSL session | 1170 // We don't need to invalidate the non-client-authenticated SSL session |
1171 // because the server will renegotiate anyway. | 1171 // because the server will renegotiate anyway. |
1172 if (client_auth_cert_needed_) | 1172 if (client_auth_cert_needed_) |
1173 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1173 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
1174 | 1174 |
1175 if (rv >= 0) | 1175 if (rv >= 0) |
1176 return rv; | 1176 return rv; |
1177 | 1177 |
1178 int err = SSL_get_error(ssl_, rv); | 1178 int err = SSL_get_error(ssl_, rv); |
1179 return MapOpenSSLError(err, err_tracer); | 1179 return MapOpenSSLError(err, err_tracer); |
1180 } | 1180 } |
1181 | 1181 |
1182 int SSLClientSocketOpenSSL::DoPayloadWrite() { | 1182 int SSLClientSocketOpenSSL::DoPayloadWrite() { |
1183 base::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 1183 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
1184 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | 1184 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
1185 | 1185 |
1186 if (rv >= 0) | 1186 if (rv >= 0) |
1187 return rv; | 1187 return rv; |
1188 | 1188 |
1189 int err = SSL_get_error(ssl_, rv); | 1189 int err = SSL_get_error(ssl_, rv); |
1190 return MapOpenSSLError(err, err_tracer); | 1190 return MapOpenSSLError(err, err_tracer); |
1191 } | 1191 } |
1192 | 1192 |
1193 } // namespace net | 1193 } // namespace net |
OLD | NEW |