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_server_socket_openssl.h" | 5 #include "net/socket/ssl_server_socket_openssl.h" |
| 6 | 6 |
| 7 #include <openssl/err.h> | 7 #include <openssl/err.h> |
| 8 #include <openssl/ssl.h> | 8 #include <openssl/ssl.h> |
| 9 | 9 |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "crypto/openssl_util.h" | 13 #include "crypto/openssl_util.h" |
| 14 #include "crypto/rsa_private_key.h" | 14 #include "crypto/rsa_private_key.h" |
| 15 #include "crypto/scoped_openssl_types.h" | 15 #include "crypto/scoped_openssl_types.h" |
| 16 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 17 #include "net/cert/cert_verify_result.h" | |
| 18 #include "net/cert/client_cert_verifier.h" | |
| 17 #include "net/ssl/openssl_ssl_util.h" | 19 #include "net/ssl/openssl_ssl_util.h" |
| 18 #include "net/ssl/scoped_openssl_types.h" | 20 #include "net/ssl/scoped_openssl_types.h" |
| 21 #include "net/ssl/ssl_connection_status_flags.h" | |
| 22 #include "net/ssl/ssl_info.h" | |
| 19 | 23 |
| 20 #define GotoState(s) next_handshake_state_ = s | 24 #define GotoState(s) next_handshake_state_ = s |
| 21 | 25 |
| 22 namespace net { | 26 namespace net { |
| 23 | 27 |
| 28 namespace { | |
| 29 | |
| 30 bool GetDERFromX509(X509* cert, base::StringPiece* sp) { | |
|
davidben
2015/12/14 23:56:49
Use net::x509_util::GetDER from x509_util_openssl.
ryanchung
2015/12/16 22:40:01
Done.
| |
| 31 unsigned char* cert_data = NULL; | |
|
davidben
2015/12/14 23:56:49
uint8_t
ryanchung
2015/12/16 22:40:01
Done.
| |
| 32 int cert_data_length = i2d_X509(cert, &cert_data); | |
| 33 if (!cert_data_length || !cert_data) { | |
| 34 return false; | |
| 35 } | |
| 36 sp->set(reinterpret_cast<char*>(cert_data), cert_data_length); | |
| 37 return true; | |
| 38 } | |
| 39 | |
| 40 scoped_refptr<X509Certificate> CreateX509Certificate(X509* cert, | |
| 41 STACK_OF(X509) * chain) { | |
| 42 DCHECK(cert); | |
| 43 std::vector<base::StringPiece> der_chain; | |
| 44 base::StringPiece der_cert; | |
| 45 scoped_refptr<X509Certificate> client_cert; | |
| 46 if (!GetDERFromX509(cert, &der_cert)) | |
| 47 return client_cert; | |
| 48 der_chain.push_back(der_cert); | |
| 49 | |
| 50 ScopedX509Stack openssl_chain(X509_chain_up_ref(chain)); | |
| 51 for (size_t i = 0; i < sk_X509_num(openssl_chain.get()); ++i) { | |
| 52 X509* x = sk_X509_value(openssl_chain.get(), i); | |
| 53 if (GetDERFromX509(x, &der_cert)) { | |
| 54 der_chain.push_back(der_cert); | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 client_cert = X509Certificate::CreateFromDERCertChain(der_chain); | |
| 59 | |
| 60 for (size_t i = 0; i < der_chain.size(); ++i) { | |
| 61 OPENSSL_free(const_cast<char*>(der_chain[i].data())); | |
| 62 } | |
| 63 if (der_chain.size() - 1 != | |
| 64 static_cast<size_t>(sk_X509_num(openssl_chain.get()))) { | |
| 65 client_cert = NULL; | |
|
davidben
2015/12/14 23:56:49
nullptr
ryanchung
2015/12/16 22:40:01
Done.
| |
| 66 } | |
| 67 return client_cert; | |
| 68 } | |
| 69 | |
| 70 } // namespace | |
| 71 | |
| 24 void EnableSSLServerSockets() { | 72 void EnableSSLServerSockets() { |
| 25 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit(). | 73 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit(). |
| 26 } | 74 } |
| 27 | 75 |
| 28 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( | 76 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( |
| 29 scoped_ptr<StreamSocket> socket, | 77 scoped_ptr<StreamSocket> socket, |
| 30 X509Certificate* certificate, | 78 X509Certificate* certificate, |
| 31 crypto::RSAPrivateKey* key, | 79 crypto::RSAPrivateKey* key, |
| 32 const SSLServerConfig& ssl_config) { | 80 const SSLServerConfig& ssl_server_config) { |
| 33 crypto::EnsureOpenSSLInit(); | 81 crypto::EnsureOpenSSLInit(); |
| 34 return scoped_ptr<SSLServerSocket>( | 82 return scoped_ptr<SSLServerSocket>(new SSLServerSocketOpenSSL( |
| 35 new SSLServerSocketOpenSSL(socket.Pass(), certificate, key, ssl_config)); | 83 socket.Pass(), certificate, key, ssl_server_config)); |
| 36 } | 84 } |
| 37 | 85 |
| 38 SSLServerSocketOpenSSL::SSLServerSocketOpenSSL( | 86 SSLServerSocketOpenSSL::SSLServerSocketOpenSSL( |
| 39 scoped_ptr<StreamSocket> transport_socket, | 87 scoped_ptr<StreamSocket> transport_socket, |
| 40 scoped_refptr<X509Certificate> certificate, | 88 scoped_refptr<X509Certificate> certificate, |
| 41 crypto::RSAPrivateKey* key, | 89 crypto::RSAPrivateKey* key, |
| 42 const SSLServerConfig& ssl_config) | 90 const SSLServerConfig& ssl_server_config) |
| 43 : transport_send_busy_(false), | 91 : transport_send_busy_(false), |
| 44 transport_recv_busy_(false), | 92 transport_recv_busy_(false), |
| 45 transport_recv_eof_(false), | 93 transport_recv_eof_(false), |
| 46 user_read_buf_len_(0), | 94 user_read_buf_len_(0), |
| 47 user_write_buf_len_(0), | 95 user_write_buf_len_(0), |
| 48 transport_write_error_(OK), | 96 transport_write_error_(OK), |
| 49 ssl_(NULL), | 97 ssl_(NULL), |
| 50 transport_bio_(NULL), | 98 transport_bio_(NULL), |
| 51 transport_socket_(transport_socket.Pass()), | 99 transport_socket_(transport_socket.Pass()), |
| 52 ssl_config_(ssl_config), | 100 ssl_server_config_(ssl_server_config), |
| 53 cert_(certificate), | 101 cert_(certificate), |
| 54 next_handshake_state_(STATE_NONE), | 102 next_handshake_state_(STATE_NONE), |
| 55 completed_handshake_(false) { | 103 completed_handshake_(false) { |
| 56 // TODO(byungchul): Need a better way to clone a key. | 104 // TODO(byungchul): Need a better way to clone a key. |
| 57 std::vector<uint8> key_bytes; | 105 std::vector<uint8> key_bytes; |
| 58 CHECK(key->ExportPrivateKey(&key_bytes)); | 106 CHECK(key->ExportPrivateKey(&key_bytes)); |
| 59 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); | 107 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); |
| 60 CHECK(key_.get()); | 108 CHECK(key_.get()); |
| 61 } | 109 } |
| 62 | 110 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 NOTIMPLEMENTED(); | 285 NOTIMPLEMENTED(); |
| 238 return false; | 286 return false; |
| 239 } | 287 } |
| 240 | 288 |
| 241 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const { | 289 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const { |
| 242 // NPN is not supported by this class. | 290 // NPN is not supported by this class. |
| 243 return kProtoUnknown; | 291 return kProtoUnknown; |
| 244 } | 292 } |
| 245 | 293 |
| 246 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { | 294 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { |
| 247 NOTIMPLEMENTED(); | 295 ssl_info->Reset(); |
| 248 return false; | 296 if (!completed_handshake_) { |
| 297 return false; | |
| 298 } | |
| 299 ExtractClientCert(); | |
| 300 ssl_info->cert = client_cert_; | |
| 301 ssl_info->client_cert_sent = | |
| 302 ssl_server_config_.require_client_cert && client_cert_.get(); | |
|
davidben
2015/12/14 23:56:49
Just client_cert_.get() seems right. Alternatively
ryanchung
2015/12/16 22:40:01
Done. Leaving it false. We can know whether we rec
| |
| 303 | |
| 304 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_); | |
| 305 CHECK(cipher); | |
| 306 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL); | |
| 307 | |
| 308 ssl_info->connection_status = | |
| 309 EncodeSSLConnectionStatus(SSL_CIPHER_get_id(cipher), | |
| 310 0 /* no compression */, GetNetSSLVersion(ssl_)); | |
| 311 | |
| 312 if (!SSL_get_secure_renegotiation_support(ssl_)) | |
| 313 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; | |
| 314 | |
| 315 ssl_info->handshake_type = SSL_session_reused(ssl_) | |
| 316 ? SSLInfo::HANDSHAKE_RESUME | |
| 317 : SSLInfo::HANDSHAKE_FULL; | |
| 318 | |
| 319 return true; | |
| 249 } | 320 } |
| 250 | 321 |
| 251 void SSLServerSocketOpenSSL::GetConnectionAttempts( | 322 void SSLServerSocketOpenSSL::GetConnectionAttempts( |
| 252 ConnectionAttempts* out) const { | 323 ConnectionAttempts* out) const { |
| 253 out->clear(); | 324 out->clear(); |
| 254 } | 325 } |
| 255 | 326 |
| 256 int64_t SSLServerSocketOpenSSL::GetTotalReceivedBytes() const { | 327 int64_t SSLServerSocketOpenSSL::GetTotalReceivedBytes() const { |
| 257 return transport_socket_->GetTotalReceivedBytes(); | 328 return transport_socket_->GetTotalReceivedBytes(); |
| 258 } | 329 } |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 int net_error = OK; | 637 int net_error = OK; |
| 567 int rv = SSL_do_handshake(ssl_); | 638 int rv = SSL_do_handshake(ssl_); |
| 568 | 639 |
| 569 if (rv == 1) { | 640 if (rv == 1) { |
| 570 completed_handshake_ = true; | 641 completed_handshake_ = true; |
| 571 } else { | 642 } else { |
| 572 int ssl_error = SSL_get_error(ssl_, rv); | 643 int ssl_error = SSL_get_error(ssl_, rv); |
| 573 OpenSSLErrorInfo error_info; | 644 OpenSSLErrorInfo error_info; |
| 574 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); | 645 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); |
| 575 | 646 |
| 647 // This hack is necessary because the mapping of SSL error codes to | |
| 648 // net_errors assumes (correctly for client sockets, but erroneously for | |
| 649 // server sockets) that peer cert verification failure can only occur if | |
| 650 // the cert changed during a renego. | |
|
davidben
2015/12/14 23:56:49
Want to file a bug about this? This is sort of a s
ryanchung
2015/12/16 22:40:01
Done. Created http://crbug.com/570351
| |
| 651 if (net_error == ERR_SSL_SERVER_CERT_CHANGED) | |
| 652 net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT; | |
| 653 | |
| 576 // If not done, stay in this state | 654 // If not done, stay in this state |
| 577 if (net_error == ERR_IO_PENDING) { | 655 if (net_error == ERR_IO_PENDING) { |
| 578 GotoState(STATE_HANDSHAKE); | 656 GotoState(STATE_HANDSHAKE); |
| 579 } else { | 657 } else { |
| 580 LOG(ERROR) << "handshake failed; returned " << rv | 658 LOG(ERROR) << "handshake failed; returned " << rv |
| 581 << ", SSL error code " << ssl_error | 659 << ", SSL error code " << ssl_error |
| 582 << ", net_error " << net_error; | 660 << ", net_error " << net_error; |
| 583 net_log_.AddEvent( | 661 net_log_.AddEvent( |
| 584 NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 662 NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 585 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); | 663 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 611 ResetAndReturn(&user_write_callback_).Run(rv); | 689 ResetAndReturn(&user_write_callback_).Run(rv); |
| 612 } | 690 } |
| 613 | 691 |
| 614 int SSLServerSocketOpenSSL::Init() { | 692 int SSLServerSocketOpenSSL::Init() { |
| 615 DCHECK(!ssl_); | 693 DCHECK(!ssl_); |
| 616 DCHECK(!transport_bio_); | 694 DCHECK(!transport_bio_); |
| 617 | 695 |
| 618 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 696 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 619 | 697 |
| 620 ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method())); | 698 ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method())); |
| 621 | 699 if (ssl_server_config_.require_client_cert) |
| 622 if (ssl_config_.require_client_cert) | |
| 623 SSL_CTX_set_verify(ssl_ctx.get(), SSL_VERIFY_PEER, NULL); | 700 SSL_CTX_set_verify(ssl_ctx.get(), SSL_VERIFY_PEER, NULL); |
| 624 | 701 SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), CertVerifyCallback, |
| 702 ssl_server_config_.client_cert_verifier); | |
| 625 ssl_ = SSL_new(ssl_ctx.get()); | 703 ssl_ = SSL_new(ssl_ctx.get()); |
| 626 if (!ssl_) | 704 if (!ssl_) |
| 627 return ERR_UNEXPECTED; | 705 return ERR_UNEXPECTED; |
| 628 | 706 |
| 629 BIO* ssl_bio = NULL; | 707 BIO* ssl_bio = NULL; |
| 630 // 0 => use default buffer sizes. | 708 // 0 => use default buffer sizes. |
| 631 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 709 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
| 632 return ERR_UNEXPECTED; | 710 return ERR_UNEXPECTED; |
| 633 DCHECK(ssl_bio); | 711 DCHECK(ssl_bio); |
| 634 DCHECK(transport_bio_); | 712 DCHECK(transport_bio_); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 661 return ERR_UNEXPECTED; | 739 return ERR_UNEXPECTED; |
| 662 } | 740 } |
| 663 #endif // USE_OPENSSL_CERTS | 741 #endif // USE_OPENSSL_CERTS |
| 664 | 742 |
| 665 DCHECK(key_->key()); | 743 DCHECK(key_->key()); |
| 666 if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) { | 744 if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) { |
| 667 LOG(ERROR) << "Cannot set private key."; | 745 LOG(ERROR) << "Cannot set private key."; |
| 668 return ERR_UNEXPECTED; | 746 return ERR_UNEXPECTED; |
| 669 } | 747 } |
| 670 | 748 |
| 671 DCHECK_LT(SSL3_VERSION, ssl_config_.version_min); | 749 DCHECK_LT(SSL3_VERSION, ssl_server_config_.version_min); |
| 672 DCHECK_LT(SSL3_VERSION, ssl_config_.version_max); | 750 DCHECK_LT(SSL3_VERSION, ssl_server_config_.version_max); |
| 673 SSL_set_min_version(ssl_, ssl_config_.version_min); | 751 SSL_set_min_version(ssl_, ssl_server_config_.version_min); |
| 674 SSL_set_max_version(ssl_, ssl_config_.version_max); | 752 SSL_set_max_version(ssl_, ssl_server_config_.version_max); |
| 675 | 753 |
| 676 // OpenSSL defaults some options to on, others to off. To avoid ambiguity, | 754 // OpenSSL defaults some options to on, others to off. To avoid ambiguity, |
| 677 // set everything we care about to an absolute value. | 755 // set everything we care about to an absolute value. |
| 678 SslSetClearMask options; | 756 SslSetClearMask options; |
| 679 options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true); | 757 options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true); |
| 680 | 758 |
| 681 SSL_set_options(ssl_, options.set_mask); | 759 SSL_set_options(ssl_, options.set_mask); |
| 682 SSL_clear_options(ssl_, options.clear_mask); | 760 SSL_clear_options(ssl_, options.clear_mask); |
| 683 | 761 |
| 684 // Same as above, this time for the SSL mode. | 762 // Same as above, this time for the SSL mode. |
| 685 SslSetClearMask mode; | 763 SslSetClearMask mode; |
| 686 | 764 |
| 687 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); | 765 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); |
| 688 | 766 |
| 689 SSL_set_mode(ssl_, mode.set_mask); | 767 SSL_set_mode(ssl_, mode.set_mask); |
| 690 SSL_clear_mode(ssl_, mode.clear_mask); | 768 SSL_clear_mode(ssl_, mode.clear_mask); |
| 691 | 769 |
| 692 // See SSLServerConfig::disabled_cipher_suites for description of the suites | 770 // See SSLServerConfig::disabled_cipher_suites for description of the suites |
| 693 // disabled by default. Note that !SHA256 and !SHA384 only remove HMAC-SHA256 | 771 // disabled by default. Note that !SHA256 and !SHA384 only remove HMAC-SHA256 |
| 694 // and HMAC-SHA384 cipher suites, not GCM cipher suites with SHA256 or SHA384 | 772 // and HMAC-SHA384 cipher suites, not GCM cipher suites with SHA256 or SHA384 |
| 695 // as the handshake hash. | 773 // as the handshake hash. |
| 696 std::string command("DEFAULT:!SHA256:!SHA384:!AESGCM+AES256:!aPSK"); | 774 std::string command("DEFAULT:!SHA256:!SHA384:!AESGCM+AES256:!aPSK"); |
| 697 | 775 |
| 698 if (ssl_config_.require_ecdhe) | 776 if (ssl_server_config_.require_ecdhe) |
| 699 command.append(":!kRSA:!kDHE"); | 777 command.append(":!kRSA:!kDHE"); |
| 700 | 778 |
| 701 // Remove any disabled ciphers. | 779 // Remove any disabled ciphers. |
| 702 for (uint16_t id : ssl_config_.disabled_cipher_suites) { | 780 for (uint16_t id : ssl_server_config_.disabled_cipher_suites) { |
| 703 const SSL_CIPHER* cipher = SSL_get_cipher_by_value(id); | 781 const SSL_CIPHER* cipher = SSL_get_cipher_by_value(id); |
| 704 if (cipher) { | 782 if (cipher) { |
| 705 command.append(":!"); | 783 command.append(":!"); |
| 706 command.append(SSL_CIPHER_get_name(cipher)); | 784 command.append(SSL_CIPHER_get_name(cipher)); |
| 707 } | 785 } |
| 708 } | 786 } |
| 709 | 787 |
| 710 int rv = SSL_set_cipher_list(ssl_, command.c_str()); | 788 int rv = SSL_set_cipher_list(ssl_, command.c_str()); |
| 711 // If this fails (rv = 0) it means there are no ciphers enabled on this SSL. | 789 // If this fails (rv = 0) it means there are no ciphers enabled on this SSL. |
| 712 // This will almost certainly result in the socket failing to complete the | 790 // This will almost certainly result in the socket failing to complete the |
| 713 // handshake at which point the appropriate error is bubbled up to the client. | 791 // handshake at which point the appropriate error is bubbled up to the client. |
| 714 LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command | 792 LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command |
| 715 << "') returned " << rv; | 793 << "') returned " << rv; |
| 716 | 794 |
| 795 if (ssl_server_config_.require_client_cert) { | |
| 796 if (ssl_server_config_.client_cert_verifier) | |
| 797 ssl_->verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; | |
|
davidben
2015/12/14 23:56:49
Please don't reach into BoringSSL's internal struc
ryanchung
2015/12/16 22:40:01
Done.
| |
| 798 if (!ssl_server_config_.client_cert_ca_list.empty()) { | |
| 799 ScopedX509NameStack stack(sk_X509_NAME_new_null()); | |
| 800 for (const auto& certificate : ssl_server_config_.client_cert_ca_list) { | |
| 801 ScopedX509 ca_cert = | |
| 802 OSCertHandleToOpenSSL(certificate->os_cert_handle()); | |
| 803 ScopedX509Name subj(X509_NAME_dup(ca_cert->cert_info->subject)); | |
| 804 sk_X509_NAME_push(stack.get(), subj.release()); | |
| 805 } | |
| 806 SSL_set_client_CA_list(ssl_, stack.release()); | |
| 807 } | |
| 808 } | |
| 809 | |
| 717 return OK; | 810 return OK; |
| 718 } | 811 } |
| 719 | 812 |
| 813 void SSLServerSocketOpenSSL::ExtractClientCert() { | |
| 814 if (client_cert_.get() || !completed_handshake_) { | |
| 815 return; | |
|
davidben
2015/12/14 23:56:49
Rather than being a function that caches stuff and
ryanchung
2015/12/16 22:40:01
Done. Will call this function only after handshake
| |
| 816 } | |
| 817 X509* cert = SSL_get_peer_certificate(ssl_); | |
| 818 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); | |
|
davidben
2015/12/14 23:56:49
NB: This is NOT the verified chain. It is the list
| |
| 819 client_cert_ = CreateX509Certificate(cert, chain); | |
| 820 } | |
| 821 | |
| 822 // static | |
| 823 int SSLServerSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx, | |
| 824 void* arg) { | |
| 825 ClientCertVerifier* verifier = reinterpret_cast<ClientCertVerifier*>(arg); | |
| 826 DCHECK(verifier); | |
|
davidben
2015/12/14 23:56:49
This DCHECK is false. You sometimes install NULL o
ryanchung
2015/12/16 22:40:01
Done.
| |
| 827 if (!verifier) | |
| 828 return 1; | |
| 829 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( | |
| 830 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); | |
| 831 DCHECK(ssl); | |
| 832 X509* x = store_ctx->cert; | |
| 833 STACK_OF(X509)* chain = store_ctx->chain; | |
|
davidben
2015/12/14 23:56:49
I believe this is always NULL. You want store_ctx-
ryanchung
2015/12/16 22:40:01
Done.
| |
| 834 scoped_refptr<X509Certificate> client_cert(CreateX509Certificate(x, chain)); | |
| 835 | |
| 836 int res = verifier->Verify(client_cert.get()); | |
| 837 if (res == OK) { | |
| 838 return 1; | |
| 839 } else { | |
| 840 X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED); | |
|
davidben
2015/12/14 23:56:49
Optional: If you also want to preserve res, OpenSS
| |
| 841 return 0; | |
| 842 } | |
| 843 } | |
| 844 | |
| 720 } // namespace net | 845 } // namespace net |
| OLD | NEW |