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