Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/err.h> | 10 #include <openssl/err.h> |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 | 234 |
| 235 // Compute a unique key string for the SSL session cache. |socket| is an | 235 // Compute a unique key string for the SSL session cache. |socket| is an |
| 236 // input socket object. Return a string. | 236 // input socket object. Return a string. |
| 237 std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) { | 237 std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) { |
| 238 std::string result = socket.host_and_port().ToString(); | 238 std::string result = socket.host_and_port().ToString(); |
| 239 result.append("/"); | 239 result.append("/"); |
| 240 result.append(socket.ssl_session_cache_shard()); | 240 result.append(socket.ssl_session_cache_shard()); |
| 241 return result; | 241 return result; |
| 242 } | 242 } |
| 243 | 243 |
| 244 // Needed by crypto::ScopedOpenSSL to properly free the certificate chain. | |
| 245 static void FreeX509Stack(STACK_OF(X509)* cert_chain) { | |
|
haavardm
2014/03/17 11:20:33
Moved this out of PeerCertificateChain, is it gave
| |
| 246 sk_X509_pop_free(cert_chain, X509_free); | |
| 247 } | |
| 248 | |
| 244 } // namespace | 249 } // namespace |
| 245 | 250 |
| 246 class SSLClientSocketOpenSSL::SSLContext { | 251 class SSLClientSocketOpenSSL::SSLContext { |
| 247 public: | 252 public: |
| 248 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } | 253 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } |
| 249 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } | 254 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } |
| 250 SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; } | 255 SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; } |
| 251 | 256 |
| 252 SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) { | 257 SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) { |
| 253 DCHECK(ssl); | 258 DCHECK(ssl); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 | 317 |
| 313 // This is the index used with SSL_get_ex_data to retrieve the owner | 318 // This is the index used with SSL_get_ex_data to retrieve the owner |
| 314 // SSLClientSocketOpenSSL object from an SSL instance. | 319 // SSLClientSocketOpenSSL object from an SSL instance. |
| 315 int ssl_socket_data_index_; | 320 int ssl_socket_data_index_; |
| 316 | 321 |
| 317 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; | 322 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; |
| 318 // |session_cache_| must be destroyed before |ssl_ctx_|. | 323 // |session_cache_| must be destroyed before |ssl_ctx_|. |
| 319 SSLSessionCacheOpenSSL session_cache_; | 324 SSLSessionCacheOpenSSL session_cache_; |
| 320 }; | 325 }; |
| 321 | 326 |
| 327 // PeerCertificateChain is a helper object which extracts the certificate | |
| 328 // chain, as given by the server, from an OpenSSL socket and performs the needed | |
| 329 // resource management. The first element of the chain is the leaf certificate | |
| 330 // and the other elements are in the order given by the server. | |
| 331 class SSLClientSocketOpenSSL::PeerCertificateChain { | |
| 332 public: | |
| 333 explicit PeerCertificateChain(SSL* ssl) { Reset(ssl); } | |
| 334 PeerCertificateChain(const PeerCertificateChain& other) { *this = other; } | |
| 335 ~PeerCertificateChain() {} | |
| 336 PeerCertificateChain& operator=(const PeerCertificateChain& other); | |
| 337 | |
| 338 // Resets the PeerCertificateChain to the set of certificates supplied by the | |
| 339 // peer of |ssl|, which may be NULL, indicating to empty the store | |
| 340 // certificates. Note: If an error occurs, such as being unable to parse the | |
| 341 // certificates, this will behave as if Reset(NULL) was called. | |
| 342 void Reset(SSL* ssl); | |
| 343 // Note that when USE_OPENSSL is defined, OSCertHandle is X509* | |
| 344 const scoped_refptr<X509Certificate>& AsOSChain() const { return os_chain_; } | |
| 345 | |
| 346 size_t size() const { | |
| 347 if (!openssl_chain_.get()) | |
| 348 return 0; | |
| 349 return sk_X509_num(openssl_chain_.get()); | |
| 350 } | |
| 351 | |
| 352 X509* operator[](size_t index) const { | |
| 353 DCHECK_LT(index, size()); | |
| 354 return sk_X509_value(openssl_chain_.get(), index); | |
| 355 } | |
| 356 | |
| 357 private: | |
| 358 crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack> openssl_chain_; | |
| 359 | |
| 360 scoped_refptr<X509Certificate> os_chain_; | |
| 361 }; | |
| 362 | |
| 363 SSLClientSocketOpenSSL::PeerCertificateChain& | |
| 364 SSLClientSocketOpenSSL::PeerCertificateChain::operator=( | |
| 365 const PeerCertificateChain& other) { | |
| 366 if (this == &other) | |
| 367 return *this; | |
| 368 | |
| 369 // os_chain_ is reference counted by scoped_refptr; | |
| 370 os_chain_ = other.os_chain_; | |
| 371 | |
| 372 // Must increase the reference count manually for sk_X509_dup | |
| 373 openssl_chain_.reset(sk_X509_dup(other.openssl_chain_.get())); | |
| 374 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { | |
| 375 X509* x = sk_X509_value(openssl_chain_.get(), i); | |
| 376 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | |
| 377 } | |
| 378 return *this; | |
| 379 } | |
| 380 | |
| 381 #if defined(USE_OPENSSL) | |
| 382 // When OSCertHandle is typedef'ed to X509, this implementation does a short cut | |
| 383 // to avoid converting back and forth between der and X509 struct. | |
| 384 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) { | |
| 385 openssl_chain_.reset(NULL); | |
| 386 os_chain_ = NULL; | |
| 387 | |
| 388 if (ssl == NULL) | |
| 389 return; | |
| 390 | |
| 391 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); | |
| 392 if (!chain) | |
| 393 return; | |
| 394 | |
| 395 X509Certificate::OSCertHandles intermediates; | |
| 396 for (int i = 1; i < sk_X509_num(chain); ++i) | |
| 397 intermediates.push_back(sk_X509_value(chain, i)); | |
| 398 | |
| 399 os_chain_ = | |
| 400 X509Certificate::CreateFromHandle(sk_X509_value(chain, 0), intermediates); | |
| 401 | |
| 402 // sk_X509_dup does not increase reference count on the certs in the stack. | |
| 403 openssl_chain_.reset(sk_X509_dup(chain)); | |
| 404 | |
| 405 std::vector<base::StringPiece> der_chain; | |
| 406 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { | |
| 407 X509* x = sk_X509_value(openssl_chain_.get(), i); | |
| 408 // Increase the reference count for the certs in openssl_chain_. | |
| 409 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | |
| 410 } | |
| 411 } | |
| 412 #else // !defined(USE_OPENSSL) | |
| 413 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) { | |
| 414 openssl_chain_.reset(NULL); | |
| 415 os_chain_ = NULL; | |
| 416 | |
| 417 if (ssl == NULL) | |
| 418 return; | |
| 419 | |
| 420 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); | |
| 421 if (!chain) | |
| 422 return; | |
| 423 | |
| 424 // sk_X509_dup does not increase reference count on the certs in the stack. | |
| 425 openssl_chain_.reset(sk_X509_dup(chain)); | |
| 426 | |
| 427 std::vector<base::StringPiece> der_chain; | |
| 428 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { | |
| 429 X509* x = sk_X509_value(openssl_chain_.get(), i); | |
| 430 | |
| 431 // Increase the reference count for the certs in openssl_chain_. | |
| 432 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | |
| 433 | |
| 434 unsigned char* cert_data = NULL; | |
| 435 int cert_data_length = i2d_X509(x, &cert_data); | |
| 436 if (cert_data_length && cert_data) | |
| 437 der_chain.push_back(base::StringPiece(reinterpret_cast<char*>(cert_data), | |
| 438 cert_data_length)); | |
| 439 } | |
| 440 | |
| 441 os_chain_ = X509Certificate::CreateFromDERCertChain(der_chain); | |
| 442 | |
| 443 for (size_t i = 0; i < der_chain.size(); ++i) { | |
| 444 OPENSSL_free(const_cast<char*>(der_chain[i].data())); | |
| 445 } | |
| 446 | |
| 447 if (der_chain.size() != | |
| 448 static_cast<size_t>(sk_X509_num(openssl_chain_.get()))) { | |
| 449 openssl_chain_.reset(NULL); | |
| 450 os_chain_ = NULL; | |
| 451 } | |
| 452 } | |
| 453 #endif // USE_OPENSSL | |
| 454 | |
| 322 // static | 455 // static |
| 323 SSLSessionCacheOpenSSL::Config | 456 SSLSessionCacheOpenSSL::Config |
| 324 SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = { | 457 SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = { |
| 325 &GetSessionCacheKey, // key_func | 458 &GetSessionCacheKey, // key_func |
| 326 1024, // max_entries | 459 1024, // max_entries |
| 327 256, // expiration_check_count | 460 256, // expiration_check_count |
| 328 60 * 60, // timeout_seconds | 461 60 * 60, // timeout_seconds |
| 329 }; | 462 }; |
| 330 | 463 |
| 331 // static | 464 // static |
| 332 void SSLClientSocket::ClearSessionCache() { | 465 void SSLClientSocket::ClearSessionCache() { |
| 333 SSLClientSocketOpenSSL::SSLContext* context = | 466 SSLClientSocketOpenSSL::SSLContext* context = |
| 334 SSLClientSocketOpenSSL::SSLContext::GetInstance(); | 467 SSLClientSocketOpenSSL::SSLContext::GetInstance(); |
| 335 context->session_cache()->Flush(); | 468 context->session_cache()->Flush(); |
| 336 OpenSSLClientKeyStore::GetInstance()->Flush(); | 469 OpenSSLClientKeyStore::GetInstance()->Flush(); |
| 337 } | 470 } |
| 338 | 471 |
| 339 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( | 472 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( |
| 340 scoped_ptr<ClientSocketHandle> transport_socket, | 473 scoped_ptr<ClientSocketHandle> transport_socket, |
| 341 const HostPortPair& host_and_port, | 474 const HostPortPair& host_and_port, |
| 342 const SSLConfig& ssl_config, | 475 const SSLConfig& ssl_config, |
| 343 const SSLClientSocketContext& context) | 476 const SSLClientSocketContext& context) |
| 344 : transport_send_busy_(false), | 477 : transport_send_busy_(false), |
| 345 transport_recv_busy_(false), | 478 transport_recv_busy_(false), |
| 346 transport_recv_eof_(false), | 479 transport_recv_eof_(false), |
| 347 weak_factory_(this), | 480 weak_factory_(this), |
| 348 pending_read_error_(kNoPendingReadResult), | 481 pending_read_error_(kNoPendingReadResult), |
| 349 transport_write_error_(OK), | 482 transport_write_error_(OK), |
| 483 server_cert_chain_(new PeerCertificateChain(NULL)), | |
| 350 completed_handshake_(false), | 484 completed_handshake_(false), |
| 351 client_auth_cert_needed_(false), | 485 client_auth_cert_needed_(false), |
| 352 cert_verifier_(context.cert_verifier), | 486 cert_verifier_(context.cert_verifier), |
| 353 server_bound_cert_service_(context.server_bound_cert_service), | 487 server_bound_cert_service_(context.server_bound_cert_service), |
| 354 ssl_(NULL), | 488 ssl_(NULL), |
| 355 transport_bio_(NULL), | 489 transport_bio_(NULL), |
| 356 transport_(transport_socket.Pass()), | 490 transport_(transport_socket.Pass()), |
| 357 host_and_port_(host_and_port), | 491 host_and_port_(host_and_port), |
| 358 ssl_config_(ssl_config), | 492 ssl_config_(ssl_config), |
| 359 ssl_session_cache_shard_(context.ssl_session_cache_shard), | 493 ssl_session_cache_shard_(context.ssl_session_cache_shard), |
| 360 trying_cached_session_(false), | 494 trying_cached_session_(false), |
| 361 next_handshake_state_(STATE_NONE), | 495 next_handshake_state_(STATE_NONE), |
| 362 npn_status_(kNextProtoUnsupported), | 496 npn_status_(kNextProtoUnsupported), |
| 363 channel_id_request_return_value_(ERR_UNEXPECTED), | 497 channel_id_request_return_value_(ERR_UNEXPECTED), |
| 364 channel_id_xtn_negotiated_(false), | 498 channel_id_xtn_negotiated_(false), |
| 365 net_log_(transport_->socket()->NetLog()) { | 499 net_log_(transport_->socket()->NetLog()) {} |
| 366 } | |
| 367 | 500 |
| 368 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | 501 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { |
| 369 Disconnect(); | 502 Disconnect(); |
| 370 } | 503 } |
| 371 | 504 |
| 372 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( | 505 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( |
| 373 SSLCertRequestInfo* cert_request_info) { | 506 SSLCertRequestInfo* cert_request_info) { |
| 374 cert_request_info->host_and_port = host_and_port_; | 507 cert_request_info->host_and_port = host_and_port_; |
| 375 cert_request_info->cert_authorities = cert_authorities_; | 508 cert_request_info->cert_authorities = cert_authorities_; |
| 376 } | 509 } |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 910 | 1043 |
| 911 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { | 1044 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { |
| 912 if (!user_connect_callback_.is_null()) { | 1045 if (!user_connect_callback_.is_null()) { |
| 913 CompletionCallback c = user_connect_callback_; | 1046 CompletionCallback c = user_connect_callback_; |
| 914 user_connect_callback_.Reset(); | 1047 user_connect_callback_.Reset(); |
| 915 c.Run(rv > OK ? OK : rv); | 1048 c.Run(rv > OK ? OK : rv); |
| 916 } | 1049 } |
| 917 } | 1050 } |
| 918 | 1051 |
| 919 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { | 1052 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { |
| 920 if (server_cert_.get()) | 1053 server_cert_chain_->Reset(ssl_); |
| 921 return server_cert_.get(); | 1054 server_cert_ = server_cert_chain_->AsOSChain(); |
| 922 | |
| 923 crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); | |
| 924 if (!cert.get()) { | |
| 925 LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; | |
| 926 return NULL; | |
| 927 } | |
| 928 | |
| 929 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not | |
| 930 // increment the reference so sk_X509_free does not need to be called. | |
| 931 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); | |
| 932 X509Certificate::OSCertHandles intermediates; | |
| 933 if (chain) { | |
| 934 for (int i = 0; i < sk_X509_num(chain); ++i) | |
| 935 intermediates.push_back(sk_X509_value(chain, i)); | |
| 936 } | |
| 937 server_cert_ = X509Certificate::CreateFromHandle(cert.get(), intermediates); | |
| 938 DCHECK(server_cert_.get()); | |
| 939 | |
| 940 return server_cert_.get(); | 1055 return server_cert_.get(); |
| 941 } | 1056 } |
| 942 | 1057 |
| 943 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { | 1058 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { |
| 944 int rv = DoHandshakeLoop(result); | 1059 int rv = DoHandshakeLoop(result); |
| 945 if (rv != ERR_IO_PENDING) { | 1060 if (rv != ERR_IO_PENDING) { |
| 946 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 1061 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
| 947 DoConnectCallback(rv); | 1062 DoConnectCallback(rv); |
| 948 } | 1063 } |
| 949 } | 1064 } |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1417 *outlen = ssl_config_.next_protos[0].size(); | 1532 *outlen = ssl_config_.next_protos[0].size(); |
| 1418 } | 1533 } |
| 1419 | 1534 |
| 1420 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); | 1535 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); |
| 1421 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); | 1536 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); |
| 1422 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; | 1537 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; |
| 1423 #endif | 1538 #endif |
| 1424 return SSL_TLSEXT_ERR_OK; | 1539 return SSL_TLSEXT_ERR_OK; |
| 1425 } | 1540 } |
| 1426 | 1541 |
| 1542 scoped_refptr<X509Certificate> | |
| 1543 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { | |
| 1544 return server_cert_; | |
| 1545 } | |
| 1546 | |
| 1427 } // namespace net | 1547 } // namespace net |
| OLD | NEW |