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

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

Issue 203323004: Do not assume OSCertHandle is OpenSSL's X509 structure. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed wtc's comments Created 6 years, 9 months 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
« 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) 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
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
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
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
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
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
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