| 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 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>( | 289 SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>( |
| 290 SSL_get_ex_data(ssl, ssl_socket_data_index_)); | 290 SSL_get_ex_data(ssl, ssl_socket_data_index_)); |
| 291 DCHECK(socket); | 291 DCHECK(socket); |
| 292 return socket; | 292 return socket; |
| 293 } | 293 } |
| 294 | 294 |
| 295 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) { | 295 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) { |
| 296 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; | 296 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; |
| 297 } | 297 } |
| 298 | 298 |
| 299 #if defined(OPENSSL_NPN_NEGOTIATED) |
| 300 static int SelectNextProtoCallback(SSL* ssl, |
| 301 unsigned char** out, unsigned char* outlen, |
| 302 const unsigned char* in, |
| 303 unsigned int inlen, void* arg) { |
| 304 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); |
| 305 return socket->SelectNextProtoCallback(out, outlen, in, inlen); |
| 306 } |
| 307 #endif |
| 308 |
| 299 private: | 309 private: |
| 300 friend struct DefaultSingletonTraits<SSLContext>; | 310 friend struct DefaultSingletonTraits<SSLContext>; |
| 301 | 311 |
| 302 SSLContext() { | 312 SSLContext() { |
| 303 base::EnsureOpenSSLInit(); | 313 base::EnsureOpenSSLInit(); |
| 304 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 314 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
| 305 DCHECK_NE(ssl_socket_data_index_, -1); | 315 DCHECK_NE(ssl_socket_data_index_, -1); |
| 306 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 316 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
| 307 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | 317 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); | 318 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); |
| 309 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); | 319 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); |
| 310 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); | 320 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); |
| 311 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); | 321 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); |
| 312 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); | 322 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); |
| 313 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); | 323 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 | |
| 321 } | 324 } |
| 322 | 325 |
| 323 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { | 326 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { |
| 324 return Get()->NewSessionCallback(ssl, session); | 327 return Get()->NewSessionCallback(ssl, session); |
| 325 } | 328 } |
| 326 | 329 |
| 327 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { | 330 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { |
| 328 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); | 331 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); |
| 329 session_cache_.OnSessionAdded(socket->host_and_port(), session); | 332 session_cache_.OnSessionAdded(socket->host_and_port(), session); |
| 330 return 1; // 1 => We took ownership of |session|. | 333 return 1; // 1 => We took ownership of |session|. |
| 331 } | 334 } |
| 332 | 335 |
| 333 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { | 336 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { |
| 334 return Get()->RemoveSessionCallback(ctx, session); | 337 return Get()->RemoveSessionCallback(ctx, session); |
| 335 } | 338 } |
| 336 | 339 |
| 337 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { | 340 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { |
| 338 DCHECK(ctx == ssl_ctx()); | 341 DCHECK(ctx == ssl_ctx()); |
| 339 session_cache_.OnSessionRemoved(session); | 342 session_cache_.OnSessionRemoved(session); |
| 340 } | 343 } |
| 341 | 344 |
| 342 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { | 345 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { |
| 343 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); | 346 SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); |
| 344 CHECK(socket); | 347 CHECK(socket); |
| 345 return socket->ClientCertRequestCallback(ssl, x509, pkey); | 348 return socket->ClientCertRequestCallback(ssl, x509, pkey); |
| 346 } | 349 } |
| 347 | 350 |
| 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 | |
| 356 // This is the index used with SSL_get_ex_data to retrieve the owner | 351 // This is the index used with SSL_get_ex_data to retrieve the owner |
| 357 // SSLClientSocketOpenSSL object from an SSL instance. | 352 // SSLClientSocketOpenSSL object from an SSL instance. |
| 358 int ssl_socket_data_index_; | 353 int ssl_socket_data_index_; |
| 359 | 354 |
| 360 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | 355 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; |
| 361 SSLSessionCache session_cache_; | 356 SSLSessionCache session_cache_; |
| 362 }; | 357 }; |
| 363 | 358 |
| 364 // Utility to construct the appropriate set & clear masks for use the OpenSSL | 359 // Utility to construct the appropriate set & clear masks for use the OpenSSL |
| 365 // options and mode configuration functions. (SSL_set_options etc) | 360 // options and mode configuration functions. (SSL_set_options etc) |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 command.append(":!"); | 498 command.append(":!"); |
| 504 command.append(name); | 499 command.append(name); |
| 505 } | 500 } |
| 506 } | 501 } |
| 507 int rv = SSL_set_cipher_list(ssl_, command.c_str()); | 502 int rv = SSL_set_cipher_list(ssl_, command.c_str()); |
| 508 // If this fails (rv = 0) it means there are no ciphers enabled on this SSL. | 503 // If this fails (rv = 0) it means there are no ciphers enabled on this SSL. |
| 509 // This will almost certainly result in the socket failing to complete the | 504 // This will almost certainly result in the socket failing to complete the |
| 510 // handshake at which point the appropriate error is bubbled up to the client. | 505 // handshake at which point the appropriate error is bubbled up to the client. |
| 511 LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command << "') " | 506 LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command << "') " |
| 512 "returned " << rv; | 507 "returned " << rv; |
| 508 |
| 509 if (!ssl_config_.next_protos.empty()) { |
| 510 #if defined(OPENSSL_NPN_NEGOTIATED) |
| 511 SSL_set_next_proto_select_cb(ssl_, SSLContext::SelectNextProtoCallback, 0); |
| 512 #else |
| 513 LOG(WARNING) << "Ignoring next_protos config"; |
| 514 #endif |
| 515 } |
| 516 |
| 513 return true; | 517 return true; |
| 514 } | 518 } |
| 515 | 519 |
| 516 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, | 520 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, |
| 517 X509** x509, | 521 X509** x509, |
| 518 EVP_PKEY** pkey) { | 522 EVP_PKEY** pkey) { |
| 519 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; | 523 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; |
| 520 DCHECK(ssl == ssl_); | 524 DCHECK(ssl == ssl_); |
| 521 DCHECK(*x509 == NULL); | 525 DCHECK(*x509 == NULL); |
| 522 DCHECK(*pkey == NULL); | 526 DCHECK(*pkey == NULL); |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 << ", SSL error code " << ssl_error | 755 << ", SSL error code " << ssl_error |
| 752 << ", net_error " << net_error; | 756 << ", net_error " << net_error; |
| 753 net_log_.AddEvent( | 757 net_log_.AddEvent( |
| 754 NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 758 NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 755 make_scoped_refptr(new SSLErrorParams(net_error, ssl_error))); | 759 make_scoped_refptr(new SSLErrorParams(net_error, ssl_error))); |
| 756 } | 760 } |
| 757 } | 761 } |
| 758 return net_error; | 762 return net_error; |
| 759 } | 763 } |
| 760 | 764 |
| 765 #if defined(OPENSSL_NPN_NEGOTIATED) |
| 761 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, | 766 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, |
| 762 unsigned char* outlen, | 767 unsigned char* outlen, |
| 763 const unsigned char* in, | 768 const unsigned char* in, |
| 764 unsigned int inlen) { | 769 unsigned int inlen) { |
| 765 #if defined(OPENSSL_NPN_NEGOTIATED) | 770 DCHECK(!ssl_config_.next_protos.empty()); |
| 766 if (ssl_config_.next_protos.empty()) { | |
| 767 *out = reinterpret_cast<uint8*>(const_cast<char*>("http/1.1")); | |
| 768 *outlen = 8; | |
| 769 npn_status_ = SSLClientSocket::kNextProtoUnsupported; | |
| 770 return SSL_TLSEXT_ERR_OK; | |
| 771 } | |
| 772 | 771 |
| 773 int status = SSL_select_next_proto( | 772 int status = SSL_select_next_proto( |
| 774 out, outlen, in, inlen, | 773 out, outlen, in, inlen, |
| 775 reinterpret_cast<const unsigned char*>(ssl_config_.next_protos.data()), | 774 reinterpret_cast<const unsigned char*>(ssl_config_.next_protos.data()), |
| 776 ssl_config_.next_protos.size()); | 775 ssl_config_.next_protos.size()); |
| 777 | 776 |
| 778 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); | 777 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); |
| 779 switch (status) { | 778 switch (status) { |
| 780 case OPENSSL_NPN_UNSUPPORTED: | 779 case OPENSSL_NPN_UNSUPPORTED: |
| 781 npn_status_ = SSLClientSocket::kNextProtoUnsupported; | 780 npn_status_ = SSLClientSocket::kNextProtoUnsupported; |
| 782 break; | 781 break; |
| 783 case OPENSSL_NPN_NEGOTIATED: | 782 case OPENSSL_NPN_NEGOTIATED: |
| 784 npn_status_ = SSLClientSocket::kNextProtoNegotiated; | 783 npn_status_ = SSLClientSocket::kNextProtoNegotiated; |
| 785 break; | 784 break; |
| 786 case OPENSSL_NPN_NO_OVERLAP: | 785 case OPENSSL_NPN_NO_OVERLAP: |
| 787 npn_status_ = SSLClientSocket::kNextProtoNoOverlap; | 786 npn_status_ = SSLClientSocket::kNextProtoNoOverlap; |
| 788 break; | 787 break; |
| 789 default: | 788 default: |
| 790 NOTREACHED() << status; | 789 NOTREACHED() << status; |
| 791 break; | 790 break; |
| 792 } | 791 } |
| 793 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; | 792 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; |
| 794 #endif | |
| 795 return SSL_TLSEXT_ERR_OK; | 793 return SSL_TLSEXT_ERR_OK; |
| 796 } | 794 } |
| 795 #endif |
| 797 | 796 |
| 798 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { | 797 int SSLClientSocketOpenSSL::DoVerifyCert(int result) { |
| 799 DCHECK(server_cert_); | 798 DCHECK(server_cert_); |
| 800 GotoState(STATE_VERIFY_CERT_COMPLETE); | 799 GotoState(STATE_VERIFY_CERT_COMPLETE); |
| 801 int flags = 0; | 800 int flags = 0; |
| 802 | 801 |
| 803 if (ssl_config_.rev_checking_enabled) | 802 if (ssl_config_.rev_checking_enabled) |
| 804 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 803 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
| 805 if (ssl_config_.verify_ev_cert) | 804 if (ssl_config_.verify_ev_cert) |
| 806 flags |= X509Certificate::VERIFY_EV_CERT; | 805 flags |= X509Certificate::VERIFY_EV_CERT; |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 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_); |
| 1173 | 1172 |
| 1174 if (rv >= 0) | 1173 if (rv >= 0) |
| 1175 return rv; | 1174 return rv; |
| 1176 | 1175 |
| 1177 int err = SSL_get_error(ssl_, rv); | 1176 int err = SSL_get_error(ssl_, rv); |
| 1178 return MapOpenSSLError(err, err_tracer); | 1177 return MapOpenSSLError(err, err_tracer); |
| 1179 } | 1178 } |
| 1180 | 1179 |
| 1181 } // namespace net | 1180 } // namespace net |
| OLD | NEW |