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 #include "net/socket/ssl_client_socket_impl.h" | 5 #include "net/socket/ssl_client_socket_impl.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <openssl/bio.h> | 8 #include <openssl/bio.h> |
| 9 #include <openssl/bytestring.h> | 9 #include <openssl/bytestring.h> |
| 10 #include <openssl/err.h> | 10 #include <openssl/err.h> |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 openssl_chain_.reset(X509_chain_up_ref(other.openssl_chain_.get())); | 442 openssl_chain_.reset(X509_chain_up_ref(other.openssl_chain_.get())); |
| 443 return *this; | 443 return *this; |
| 444 } | 444 } |
| 445 | 445 |
| 446 void SSLClientSocketImpl::PeerCertificateChain::Reset(STACK_OF(X509) * chain) { | 446 void SSLClientSocketImpl::PeerCertificateChain::Reset(STACK_OF(X509) * chain) { |
| 447 openssl_chain_.reset(chain ? X509_chain_up_ref(chain) : NULL); | 447 openssl_chain_.reset(chain ? X509_chain_up_ref(chain) : NULL); |
| 448 } | 448 } |
| 449 | 449 |
| 450 scoped_refptr<X509Certificate> | 450 scoped_refptr<X509Certificate> |
| 451 SSLClientSocketImpl::PeerCertificateChain::AsOSChain() const { | 451 SSLClientSocketImpl::PeerCertificateChain::AsOSChain() const { |
| 452 #if defined(USE_OPENSSL_CERTS) | 452 // DER-encode the chain and convert to a platform certificate handle. |
|
davidben
2016/08/31 19:20:49
Hrm. This does mean that the SSLClientSocketImpl w
Ryan Sleevi
2016/08/31 20:33:13
We were sharing (de-duping) the first X509* (X509*
| |
| 453 // When OSCertHandle is typedef'ed to X509, this implementation does a short | 453 std::vector<std::string> chain; |
| 454 // cut to avoid converting back and forth between DER and the X509 struct. | 454 std::vector<base::StringPiece> stringpiece_chain; |
| 455 X509Certificate::OSCertHandles intermediates; | 455 for (size_t i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { |
| 456 for (size_t i = 1; i < sk_X509_num(openssl_chain_.get()); ++i) { | 456 X509* x = sk_X509_value(openssl_chain_.get(), i); |
| 457 intermediates.push_back(sk_X509_value(openssl_chain_.get(), i)); | 457 // Note: This intentionally avoids using x509_util::GetDER(), which may |
| 458 // cache the encoded DER on |x|, as |x| is shared with the underlying | |
| 459 // socket (SSL*) this chain belongs to. As the DER will only be used | |
| 460 // once in //net, within this code, this avoids needlessly caching | |
| 461 // additional data. See https://crbug.com/642082 | |
| 462 int len = i2d_X509(x, nullptr); | |
| 463 if (len < 0) | |
| 464 return nullptr; | |
| 465 std::string cert; | |
| 466 uint8_t* ptr = reinterpret_cast<uint8_t*>(base::WriteInto(&cert, len + 1)); | |
| 467 if (i2d_X509(x, &ptr) < 0) { | |
| 468 NOTREACHED(); | |
| 469 return nullptr; | |
| 470 } | |
| 471 chain.emplace_back(cert); | |
| 472 stringpiece_chain.push_back(chain.back()); | |
| 458 } | 473 } |
| 459 | 474 |
| 460 return X509Certificate::CreateFromHandle( | 475 return X509Certificate::CreateFromDERCertChain(stringpiece_chain); |
| 461 sk_X509_value(openssl_chain_.get(), 0), intermediates); | |
| 462 #else | |
| 463 // DER-encode the chain and convert to a platform certificate handle. | |
| 464 std::vector<base::StringPiece> der_chain; | |
| 465 for (size_t i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { | |
| 466 X509* x = sk_X509_value(openssl_chain_.get(), i); | |
| 467 base::StringPiece der; | |
| 468 if (!x509_util::GetDER(x, &der)) | |
| 469 return NULL; | |
| 470 der_chain.push_back(der); | |
| 471 } | |
| 472 | |
| 473 return X509Certificate::CreateFromDERCertChain(der_chain); | |
| 474 #endif | |
| 475 } | 476 } |
| 476 | 477 |
| 477 // static | 478 // static |
| 478 void SSLClientSocket::ClearSessionCache() { | 479 void SSLClientSocket::ClearSessionCache() { |
| 479 SSLClientSocketImpl::SSLContext* context = | 480 SSLClientSocketImpl::SSLContext* context = |
| 480 SSLClientSocketImpl::SSLContext::GetInstance(); | 481 SSLClientSocketImpl::SSLContext::GetInstance(); |
| 481 context->session_cache()->Flush(); | 482 context->session_cache()->Flush(); |
| 482 } | 483 } |
| 483 | 484 |
| 484 SSLClientSocketImpl::SSLClientSocketImpl( | 485 SSLClientSocketImpl::SSLClientSocketImpl( |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1286 | 1287 |
| 1287 int SSLClientSocketImpl::DoVerifyCert(int result) { | 1288 int SSLClientSocketImpl::DoVerifyCert(int result) { |
| 1288 DCHECK(!server_cert_chain_->empty()); | 1289 DCHECK(!server_cert_chain_->empty()); |
| 1289 DCHECK(start_cert_verification_time_.is_null()); | 1290 DCHECK(start_cert_verification_time_.is_null()); |
| 1290 | 1291 |
| 1291 next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE; | 1292 next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE; |
| 1292 | 1293 |
| 1293 // OpenSSL decoded the certificate, but the platform certificate | 1294 // OpenSSL decoded the certificate, but the platform certificate |
| 1294 // implementation could not. This is treated as a fatal SSL-level protocol | 1295 // implementation could not. This is treated as a fatal SSL-level protocol |
| 1295 // error rather than a certificate error. See https://crbug.com/91341. | 1296 // error rather than a certificate error. See https://crbug.com/91341. |
| 1296 if (!server_cert_.get()) | 1297 if (!server_cert_) |
| 1297 return ERR_SSL_SERVER_CERT_BAD_FORMAT; | 1298 return ERR_SSL_SERVER_CERT_BAD_FORMAT; |
| 1298 | 1299 |
| 1299 // If the certificate is bad and has been previously accepted, use | 1300 // If the certificate is bad and has been previously accepted, use |
| 1300 // the previous status and bypass the error. | 1301 // the previous status and bypass the error. |
| 1301 base::StringPiece der_cert; | |
| 1302 if (!x509_util::GetDER(server_cert_chain_->Get(0), &der_cert)) { | |
| 1303 NOTREACHED(); | |
| 1304 return ERR_CERT_INVALID; | |
| 1305 } | |
| 1306 CertStatus cert_status; | 1302 CertStatus cert_status; |
| 1307 if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) { | 1303 if (ssl_config_.IsAllowedBadCert(server_cert_.get(), &cert_status)) { |
| 1308 server_cert_verify_result_.Reset(); | 1304 server_cert_verify_result_.Reset(); |
| 1309 server_cert_verify_result_.cert_status = cert_status; | 1305 server_cert_verify_result_.cert_status = cert_status; |
| 1310 server_cert_verify_result_.verified_cert = server_cert_; | 1306 server_cert_verify_result_.verified_cert = server_cert_; |
| 1311 return OK; | 1307 return OK; |
| 1312 } | 1308 } |
| 1313 | 1309 |
| 1314 start_cert_verification_time_ = base::TimeTicks::Now(); | 1310 start_cert_verification_time_ = base::TimeTicks::Now(); |
| 1315 | 1311 |
| 1316 return cert_verifier_->Verify( | 1312 return cert_verifier_->Verify( |
| 1317 CertVerifier::RequestParams(server_cert_, host_and_port_.host(), | 1313 CertVerifier::RequestParams(server_cert_, host_and_port_.host(), |
| (...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2382 } | 2378 } |
| 2383 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported, | 2379 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported, |
| 2384 CHANNEL_ID_USAGE_MAX); | 2380 CHANNEL_ID_USAGE_MAX); |
| 2385 } | 2381 } |
| 2386 | 2382 |
| 2387 bool SSLClientSocketImpl::IsChannelIDEnabled() const { | 2383 bool SSLClientSocketImpl::IsChannelIDEnabled() const { |
| 2388 return ssl_config_.channel_id_enabled && channel_id_service_; | 2384 return ssl_config_.channel_id_enabled && channel_id_service_; |
| 2389 } | 2385 } |
| 2390 | 2386 |
| 2391 } // namespace net | 2387 } // namespace net |
| OLD | NEW |