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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 // |session_cache_| must be destroyed before |ssl_ctx_|. | 325 // |session_cache_| must be destroyed before |ssl_ctx_|. |
326 SSLSessionCacheOpenSSL session_cache_; | 326 SSLSessionCacheOpenSSL session_cache_; |
327 }; | 327 }; |
328 | 328 |
329 // PeerCertificateChain is a helper object which extracts the certificate | 329 // PeerCertificateChain is a helper object which extracts the certificate |
330 // chain, as given by the server, from an OpenSSL socket and performs the needed | 330 // chain, as given by the server, from an OpenSSL socket and performs the needed |
331 // resource management. The first element of the chain is the leaf certificate | 331 // resource management. The first element of the chain is the leaf certificate |
332 // and the other elements are in the order given by the server. | 332 // and the other elements are in the order given by the server. |
333 class SSLClientSocketOpenSSL::PeerCertificateChain { | 333 class SSLClientSocketOpenSSL::PeerCertificateChain { |
334 public: | 334 public: |
335 explicit PeerCertificateChain(SSL* ssl) { Reset(ssl); } | 335 explicit PeerCertificateChain(STACK_OF(X509)* chain) { Reset(chain); } |
336 PeerCertificateChain(const PeerCertificateChain& other) { *this = other; } | 336 PeerCertificateChain(const PeerCertificateChain& other) { *this = other; } |
337 ~PeerCertificateChain() {} | 337 ~PeerCertificateChain() {} |
338 PeerCertificateChain& operator=(const PeerCertificateChain& other); | 338 PeerCertificateChain& operator=(const PeerCertificateChain& other); |
339 | 339 |
340 // Resets the PeerCertificateChain to the set of certificates supplied by the | 340 // Resets the PeerCertificateChain to the set of certificates in|chain|, |
341 // peer of |ssl|, which may be NULL, indicating to empty the store | 341 // which may be NULL, indicating to empty the store certificates. |
342 // certificates. Note: If an error occurs, such as being unable to parse the | 342 // Note: If an error occurs, such as being unable to parse the certificates, |
343 // certificates, this will behave as if Reset(NULL) was called. | 343 // this will behave as if Reset(NULL) was called. |
344 void Reset(SSL* ssl); | 344 void Reset(STACK_OF(X509)* chain); |
| 345 |
345 // Note that when USE_OPENSSL is defined, OSCertHandle is X509* | 346 // Note that when USE_OPENSSL is defined, OSCertHandle is X509* |
346 const scoped_refptr<X509Certificate>& AsOSChain() const { return os_chain_; } | 347 const scoped_refptr<X509Certificate>& AsOSChain() const { return os_chain_; } |
347 | 348 |
348 size_t size() const { | 349 size_t size() const { |
349 if (!openssl_chain_.get()) | 350 if (!openssl_chain_.get()) |
350 return 0; | 351 return 0; |
351 return sk_X509_num(openssl_chain_.get()); | 352 return sk_X509_num(openssl_chain_.get()); |
352 } | 353 } |
353 | 354 |
354 X509* operator[](size_t index) const { | 355 X509* operator[](size_t index) const { |
355 DCHECK_LT(index, size()); | 356 DCHECK_LT(index, size()); |
356 return sk_X509_value(openssl_chain_.get(), index); | 357 return sk_X509_value(openssl_chain_.get(), index); |
357 } | 358 } |
358 | 359 |
| 360 bool IsValid() { return os_chain_.get() && openssl_chain_.get(); } |
| 361 |
359 private: | 362 private: |
360 static void FreeX509Stack(STACK_OF(X509)* cert_chain) { | 363 static void FreeX509Stack(STACK_OF(X509)* cert_chain) { |
361 sk_X509_pop_free(cert_chain, X509_free); | 364 sk_X509_pop_free(cert_chain, X509_free); |
362 } | 365 } |
363 | 366 |
364 friend class crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>; | 367 friend class crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>; |
365 | 368 |
366 crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack> openssl_chain_; | 369 crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack> openssl_chain_; |
367 | 370 |
368 scoped_refptr<X509Certificate> os_chain_; | 371 scoped_refptr<X509Certificate> os_chain_; |
(...skipping 13 matching lines...) Expand all Loading... |
382 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { | 385 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { |
383 X509* x = sk_X509_value(openssl_chain_.get(), i); | 386 X509* x = sk_X509_value(openssl_chain_.get(), i); |
384 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | 387 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); |
385 } | 388 } |
386 return *this; | 389 return *this; |
387 } | 390 } |
388 | 391 |
389 #if defined(USE_OPENSSL) | 392 #if defined(USE_OPENSSL) |
390 // When OSCertHandle is typedef'ed to X509, this implementation does a short cut | 393 // When OSCertHandle is typedef'ed to X509, this implementation does a short cut |
391 // to avoid converting back and forth between der and X509 struct. | 394 // to avoid converting back and forth between der and X509 struct. |
392 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) { | 395 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset( |
| 396 STACK_OF(X509)* chain) { |
393 openssl_chain_.reset(NULL); | 397 openssl_chain_.reset(NULL); |
394 os_chain_ = NULL; | 398 os_chain_ = NULL; |
395 | 399 |
396 if (ssl == NULL) | |
397 return; | |
398 | |
399 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); | |
400 if (!chain) | 400 if (!chain) |
401 return; | 401 return; |
402 | 402 |
403 X509Certificate::OSCertHandles intermediates; | 403 X509Certificate::OSCertHandles intermediates; |
404 for (int i = 1; i < sk_X509_num(chain); ++i) | 404 for (int i = 1; i < sk_X509_num(chain); ++i) |
405 intermediates.push_back(sk_X509_value(chain, i)); | 405 intermediates.push_back(sk_X509_value(chain, i)); |
406 | 406 |
407 os_chain_ = | 407 os_chain_ = |
408 X509Certificate::CreateFromHandle(sk_X509_value(chain, 0), intermediates); | 408 X509Certificate::CreateFromHandle(sk_X509_value(chain, 0), intermediates); |
409 | 409 |
410 // sk_X509_dup does not increase reference count on the certs in the stack. | 410 // sk_X509_dup does not increase reference count on the certs in the stack. |
411 openssl_chain_.reset(sk_X509_dup(chain)); | 411 openssl_chain_.reset(sk_X509_dup(chain)); |
412 | 412 |
413 std::vector<base::StringPiece> der_chain; | 413 std::vector<base::StringPiece> der_chain; |
414 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { | 414 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { |
415 X509* x = sk_X509_value(openssl_chain_.get(), i); | 415 X509* x = sk_X509_value(openssl_chain_.get(), i); |
416 // Increase the reference count for the certs in openssl_chain_. | 416 // Increase the reference count for the certs in openssl_chain_. |
417 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | 417 CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); |
418 } | 418 } |
419 } | 419 } |
420 #else // !defined(USE_OPENSSL) | 420 #else // !defined(USE_OPENSSL) |
421 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(SSL* ssl) { | 421 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset( |
| 422 STACK_OF(X509)* chain) { |
422 openssl_chain_.reset(NULL); | 423 openssl_chain_.reset(NULL); |
423 os_chain_ = NULL; | 424 os_chain_ = NULL; |
424 | 425 |
425 if (ssl == NULL) | |
426 return; | |
427 | |
428 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); | |
429 if (!chain) | 426 if (!chain) |
430 return; | 427 return; |
431 | 428 |
432 // sk_X509_dup does not increase reference count on the certs in the stack. | 429 // sk_X509_dup does not increase reference count on the certs in the stack. |
433 openssl_chain_.reset(sk_X509_dup(chain)); | 430 openssl_chain_.reset(sk_X509_dup(chain)); |
434 | 431 |
435 std::vector<base::StringPiece> der_chain; | 432 std::vector<base::StringPiece> der_chain; |
436 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { | 433 for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { |
437 X509* x = sk_X509_value(openssl_chain_.get(), i); | 434 X509* x = sk_X509_value(openssl_chain_.get(), i); |
438 | 435 |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 | 1048 |
1052 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { | 1049 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { |
1053 if (!user_connect_callback_.is_null()) { | 1050 if (!user_connect_callback_.is_null()) { |
1054 CompletionCallback c = user_connect_callback_; | 1051 CompletionCallback c = user_connect_callback_; |
1055 user_connect_callback_.Reset(); | 1052 user_connect_callback_.Reset(); |
1056 c.Run(rv > OK ? OK : rv); | 1053 c.Run(rv > OK ? OK : rv); |
1057 } | 1054 } |
1058 } | 1055 } |
1059 | 1056 |
1060 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { | 1057 X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { |
1061 server_cert_chain_->Reset(ssl_); | 1058 server_cert_chain_->Reset(SSL_get_peer_cert_chain(ssl_)); |
1062 server_cert_ = server_cert_chain_->AsOSChain(); | 1059 server_cert_ = server_cert_chain_->AsOSChain(); |
| 1060 |
| 1061 if (!server_cert_chain_->IsValid()) |
| 1062 DVLOG(1) << "UpdateServerCert received invalid certificate chain from peer"; |
| 1063 |
1063 return server_cert_.get(); | 1064 return server_cert_.get(); |
1064 } | 1065 } |
1065 | 1066 |
1066 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { | 1067 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { |
1067 int rv = DoHandshakeLoop(result); | 1068 int rv = DoHandshakeLoop(result); |
1068 if (rv != ERR_IO_PENDING) { | 1069 if (rv != ERR_IO_PENDING) { |
1069 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); | 1070 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); |
1070 DoConnectCallback(rv); | 1071 DoConnectCallback(rv); |
1071 } | 1072 } |
1072 } | 1073 } |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1495 *pkey = EVP_PKEY_dup(ec_private_key->key()); | 1496 *pkey = EVP_PKEY_dup(ec_private_key->key()); |
1496 } | 1497 } |
1497 | 1498 |
1498 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { | 1499 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { |
1499 if (!completed_handshake_) { | 1500 if (!completed_handshake_) { |
1500 // If the first handshake hasn't completed then we accept any certificates | 1501 // If the first handshake hasn't completed then we accept any certificates |
1501 // because we verify after the handshake. | 1502 // because we verify after the handshake. |
1502 return 1; | 1503 return 1; |
1503 } | 1504 } |
1504 | 1505 |
1505 if (X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), | 1506 CHECK(server_cert_.get()); |
1506 sk_X509_value(store_ctx->untrusted, 0))) { | 1507 |
| 1508 PeerCertificateChain chain(store_ctx->chain); |
| 1509 if (chain.IsValid() && server_cert_->Equals(chain.AsOSChain())) |
1507 return 1; | 1510 return 1; |
1508 } | |
1509 | 1511 |
1510 LOG(ERROR) << "Server certificate changed between handshakes"; | 1512 if (!chain.IsValid()) |
| 1513 LOG(ERROR) << "Received invalid certificate chain between handshakes"; |
| 1514 else |
| 1515 LOG(ERROR) << "Server certificate changed between handshakes"; |
1511 return 0; | 1516 return 0; |
1512 } | 1517 } |
1513 | 1518 |
1514 // SelectNextProtoCallback is called by OpenSSL during the handshake. If the | 1519 // SelectNextProtoCallback is called by OpenSSL during the handshake. If the |
1515 // server supports NPN, selects a protocol from the list that the server | 1520 // server supports NPN, selects a protocol from the list that the server |
1516 // provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the | 1521 // provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the |
1517 // callback can assume that |in| is syntactically valid. | 1522 // callback can assume that |in| is syntactically valid. |
1518 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, | 1523 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, |
1519 unsigned char* outlen, | 1524 unsigned char* outlen, |
1520 const unsigned char* in, | 1525 const unsigned char* in, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 #endif | 1567 #endif |
1563 return SSL_TLSEXT_ERR_OK; | 1568 return SSL_TLSEXT_ERR_OK; |
1564 } | 1569 } |
1565 | 1570 |
1566 scoped_refptr<X509Certificate> | 1571 scoped_refptr<X509Certificate> |
1567 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { | 1572 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { |
1568 return server_cert_; | 1573 return server_cert_; |
1569 } | 1574 } |
1570 | 1575 |
1571 } // namespace net | 1576 } // namespace net |
OLD | NEW |