Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: net/socket/ssl_client_socket_openssl.cc

Issue 5728001: Set NPN callback per connection (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698