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> |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 304 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
305 DCHECK_NE(ssl_socket_data_index_, -1); | 305 DCHECK_NE(ssl_socket_data_index_, -1); |
306 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 306 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
307 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | 307 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); |
308 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); | 308 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); |
309 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); | 309 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); |
310 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); | 310 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); |
311 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); | 311 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); |
312 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); | 312 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); |
313 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); | 313 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); |
| 314 #if defined(OPENSSL_NPN_NEGOTIATED) |
| 315 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. |
| 316 // It would be better if the callback were not a global setting, |
| 317 // but that is an OpenSSL issue. |
| 318 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, |
| 319 NULL); |
| 320 #endif |
314 } | 321 } |
315 | 322 |
316 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { | 323 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { |
317 return Get()->NewSessionCallback(ssl, session); | 324 return Get()->NewSessionCallback(ssl, session); |
318 } | 325 } |
319 | 326 |
320 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { | 327 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { |
321 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); | 328 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); |
322 session_cache_.OnSessionAdded(socket->host_and_port(), session); | 329 session_cache_.OnSessionAdded(socket->host_and_port(), session); |
323 return 1; // 1 => We took ownership of |session|. | 330 return 1; // 1 => We took ownership of |session|. |
324 } | 331 } |
325 | 332 |
326 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { | 333 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { |
327 return Get()->RemoveSessionCallback(ctx, session); | 334 return Get()->RemoveSessionCallback(ctx, session); |
328 } | 335 } |
329 | 336 |
330 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { | 337 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { |
331 DCHECK(ctx == ssl_ctx()); | 338 DCHECK(ctx == ssl_ctx()); |
332 session_cache_.OnSessionRemoved(session); | 339 session_cache_.OnSessionRemoved(session); |
333 } | 340 } |
334 | 341 |
335 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { | 342 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { |
336 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); | 343 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); |
337 CHECK(socket); | 344 CHECK(socket); |
338 return socket->ClientCertRequestCallback(ssl, x509, pkey); | 345 return socket->ClientCertRequestCallback(ssl, x509, pkey); |
339 } | 346 } |
340 | 347 |
| 348 static int SelectNextProtoCallback(SSL* ssl, |
| 349 unsigned char** out, unsigned char* outlen, |
| 350 const unsigned char* in, |
| 351 unsigned int inlen, void* arg) { |
| 352 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); |
| 353 return socket->SelectNextProtoCallback(out, outlen, in, inlen); |
| 354 } |
| 355 |
341 // This is the index used with SSL_get_ex_data to retrieve the owner | 356 // This is the index used with SSL_get_ex_data to retrieve the owner |
342 // SSLClientSocketOpenSSL object from an SSL instance. | 357 // SSLClientSocketOpenSSL object from an SSL instance. |
343 int ssl_socket_data_index_; | 358 int ssl_socket_data_index_; |
344 | 359 |
345 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | 360 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; |
346 SSLSessionCache session_cache_; | 361 SSLSessionCache session_cache_; |
347 }; | 362 }; |
348 | 363 |
349 // Utility to construct the appropriate set & clear masks for use the OpenSSL | 364 // Utility to construct the appropriate set & clear masks for use the OpenSSL |
350 // options and mode configuration functions. (SSL_set_options etc) | 365 // options and mode configuration functions. (SSL_set_options etc) |
(...skipping 26 matching lines...) Expand all Loading... |
377 completed_handshake_(false), | 392 completed_handshake_(false), |
378 client_auth_cert_needed_(false), | 393 client_auth_cert_needed_(false), |
379 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( | 394 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( |
380 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)), | 395 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)), |
381 ssl_(NULL), | 396 ssl_(NULL), |
382 transport_bio_(NULL), | 397 transport_bio_(NULL), |
383 transport_(transport_socket), | 398 transport_(transport_socket), |
384 host_and_port_(host_and_port), | 399 host_and_port_(host_and_port), |
385 ssl_config_(ssl_config), | 400 ssl_config_(ssl_config), |
386 trying_cached_session_(false), | 401 trying_cached_session_(false), |
| 402 npn_status_(kNextProtoUnsupported), |
387 net_log_(transport_socket->socket()->NetLog()) { | 403 net_log_(transport_socket->socket()->NetLog()) { |
388 } | 404 } |
389 | 405 |
390 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | 406 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { |
391 Disconnect(); | 407 Disconnect(); |
392 } | 408 } |
393 | 409 |
394 bool SSLClientSocketOpenSSL::Init() { | 410 bool SSLClientSocketOpenSSL::Init() { |
395 DCHECK(!ssl_); | 411 DCHECK(!ssl_); |
396 DCHECK(!transport_bio_); | 412 DCHECK(!transport_bio_); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 } | 576 } |
561 | 577 |
562 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( | 578 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( |
563 SSLCertRequestInfo* cert_request_info) { | 579 SSLCertRequestInfo* cert_request_info) { |
564 cert_request_info->host_and_port = host_and_port_.ToString(); | 580 cert_request_info->host_and_port = host_and_port_.ToString(); |
565 cert_request_info->client_certs = client_certs_; | 581 cert_request_info->client_certs = client_certs_; |
566 } | 582 } |
567 | 583 |
568 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( | 584 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( |
569 std::string* proto) { | 585 std::string* proto) { |
570 proto->clear(); | 586 *proto = npn_proto_; |
571 return kNextProtoUnsupported; | 587 return npn_status_; |
572 } | 588 } |
573 | 589 |
574 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { | 590 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { |
575 // Since Run may result in Read being called, clear |user_read_callback_| | 591 // Since Run may result in Read being called, clear |user_read_callback_| |
576 // up front. | 592 // up front. |
577 CompletionCallback* c = user_read_callback_; | 593 CompletionCallback* c = user_read_callback_; |
578 user_read_callback_ = NULL; | 594 user_read_callback_ = NULL; |
579 user_read_buf_ = NULL; | 595 user_read_buf_ = NULL; |
580 user_read_buf_len_ = 0; | 596 user_read_buf_len_ = 0; |
581 c->Run(rv); | 597 c->Run(rv); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 << ", SSL error code " << ssl_error | 751 << ", SSL error code " << ssl_error |
736 << ", net_error " << net_error; | 752 << ", net_error " << net_error; |
737 net_log_.AddEvent( | 753 net_log_.AddEvent( |
738 NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 754 NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
739 make_scoped_refptr(new SSLErrorParams(net_error, ssl_error))); | 755 make_scoped_refptr(new SSLErrorParams(net_error, ssl_error))); |
740 } | 756 } |
741 } | 757 } |
742 return net_error; | 758 return net_error; |
743 } | 759 } |
744 | 760 |
| 761 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, |
| 762 unsigned char* outlen, |
| 763 const unsigned char* in, |
| 764 unsigned int inlen) { |
| 765 #if defined(OPENSSL_NPN_NEGOTIATED) |
| 766 if (ssl_config_.next_protos.empty()) { |
| 767 *out = "http/1.1"; |
| 768 *outlen = 8; |
| 769 npn_status_ = SSLClientSocket::kNextProtoUnsupported; |
| 770 return SSL_TLSEXT_ERR_OK; |
| 771 } |
| 772 |
| 773 int status = SSL_select_next_proto( |
| 774 out, outlen, in, inlen, |
| 775 reinterpret_cast<const unsigned char*>(ssl_config_.next_protos.data()), |
| 776 ssl_config_.next_protos.size()); |
| 777 |
| 778 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); |
| 779 switch (status) { |
| 780 case OPENSSL_NPN_UNSUPPORTED: |
| 781 npn_status_ = SSLClientSocket::kNextProtoUnsupported; |
| 782 break; |
| 783 case OPENSSL_NPN_NEGOTIATED: |
| 784 npn_status_ = SSLClientSocket::kNextProtoNegotiated; |
| 785 break; |
| 786 case OPENSSL_NPN_NO_OVERLAP: |
| 787 npn_status_ = SSLClientSocket::kNextProtoNoOverlap; |
| 788 break; |
| 789 default: |
| 790 NOTREACHED() << status; |
| 791 break; |
| 792 } |
| 793 #endif |
| 794 return SSL_TLSEXT_ERR_OK; |
| 795 } |
| 796 |
745 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { | 797 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { |
746 DCHECK(server_cert_); | 798 DCHECK(server_cert_); |
747 GotoState(STATE_VERIFY_CERT_COMPLETE); | 799 GotoState(STATE_VERIFY_CERT_COMPLETE); |
748 int flags = 0; | 800 int flags = 0; |
749 | 801 |
750 if (ssl_config_.rev_checking_enabled) | 802 if (ssl_config_.rev_checking_enabled) |
751 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 803 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
752 if (ssl_config_.verify_ev_cert) | 804 if (ssl_config_.verify_ev_cert) |
753 flags |= X509Certificate::VERIFY_EV_CERT; | 805 flags |= X509Certificate::VERIFY_EV_CERT; |
754 verifier_.reset(new CertVerifier); | 806 verifier_.reset(new CertVerifier); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | 1171 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
1120 | 1172 |
1121 if (rv >= 0) | 1173 if (rv >= 0) |
1122 return rv; | 1174 return rv; |
1123 | 1175 |
1124 int err = SSL_get_error(ssl_, rv); | 1176 int err = SSL_get_error(ssl_, rv); |
1125 return MapOpenSSLError(err, err_tracer); | 1177 return MapOpenSSLError(err, err_tracer); |
1126 } | 1178 } |
1127 | 1179 |
1128 } // namespace net | 1180 } // namespace net |
OLD | NEW |