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 "crypto/openssl_util.h" | 12 #include "crypto/openssl_util.h" |
| 13 #include "crypto/rsa_private_key.h" | 13 #include "crypto/rsa_private_key.h" |
| 14 #include "crypto/scoped_openssl_types.h" | 14 #include "crypto/scoped_openssl_types.h" |
| 15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
| 16 #include "net/cert/cert_verifier.h" | |
| 17 #include "net/cert/cert_verify_result.h" | |
| 16 #include "net/ssl/openssl_ssl_util.h" | 18 #include "net/ssl/openssl_ssl_util.h" |
| 17 #include "net/ssl/scoped_openssl_types.h" | 19 #include "net/ssl/scoped_openssl_types.h" |
| 20 #include "net/ssl/ssl_connection_status_flags.h" | |
| 21 #include "net/ssl/ssl_info.h" | |
| 18 | 22 |
| 19 #define GotoState(s) next_handshake_state_ = s | 23 #define GotoState(s) next_handshake_state_ = s |
| 20 | 24 |
| 21 namespace net { | 25 namespace net { |
| 22 | 26 |
| 27 namespace { | |
| 28 | |
| 29 // TODO(dougsteed) These definitions copied from ssl_client_socket_openssl.cc. | |
| 30 // Might want to consider putting them in a common place. | |
|
Ryan Sleevi
2015/03/19 04:38:25
Yes. Copy pasta bad.
| |
| 31 void FreeX509Stack(STACK_OF(X509) * ptr) { | |
| 32 sk_X509_pop_free(ptr, X509_free); | |
| 33 } | |
| 34 | |
| 35 void FreeX509NameStack(STACK_OF(X509_NAME) * ptr) { | |
| 36 sk_X509_NAME_pop_free(ptr, X509_NAME_free); | |
| 37 } | |
| 38 | |
| 39 typedef crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free> ScopedX509Name; | |
| 40 typedef crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack> ScopedX509Stack; | |
| 41 typedef crypto::ScopedOpenSSL<STACK_OF(X509_NAME), FreeX509NameStack> | |
| 42 ScopedX509NameStack; | |
| 43 | |
| 44 #if OPENSSL_VERSION_NUMBER < 0x1000103fL | |
|
Ryan Sleevi
2015/03/19 04:38:25
Does this matter at all David?
| |
| 45 // This method doesn't seem to have made it into the OpenSSL headers. | |
| 46 unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { | |
| 47 return cipher->id; | |
| 48 } | |
| 49 #endif | |
| 50 | |
| 51 // Used for encoding the |connection_status| field of an SSLInfo object. | |
| 52 int EncodeSSLConnectionStatus(int cipher_suite, int compression, int version) { | |
| 53 return (cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) | | |
| 54 ((compression & SSL_CONNECTION_COMPRESSION_MASK) | |
| 55 << SSL_CONNECTION_COMPRESSION_SHIFT) | | |
| 56 ((version & SSL_CONNECTION_VERSION_MASK) | |
| 57 << SSL_CONNECTION_VERSION_SHIFT); | |
| 58 } | |
| 59 | |
| 60 // Returns the net SSL version number (see ssl_connection_status_flags.h) for | |
| 61 // this SSL connection. | |
| 62 int GetNetSSLVersion(SSL* ssl) { | |
| 63 switch (SSL_version(ssl)) { | |
| 64 case SSL2_VERSION: | |
| 65 return SSL_CONNECTION_VERSION_SSL2; | |
| 66 case SSL3_VERSION: | |
| 67 return SSL_CONNECTION_VERSION_SSL3; | |
| 68 case TLS1_VERSION: | |
| 69 return SSL_CONNECTION_VERSION_TLS1; | |
| 70 case 0x0302: | |
| 71 return SSL_CONNECTION_VERSION_TLS1_1; | |
| 72 case 0x0303: | |
| 73 return SSL_CONNECTION_VERSION_TLS1_2; | |
| 74 default: | |
| 75 return SSL_CONNECTION_VERSION_UNKNOWN; | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 bool GetX509AsDER(X509* cert, base::StringPiece* sp) { | |
|
Ryan Sleevi
2015/03/19 04:38:25
name better
| |
| 80 unsigned char* cert_data = NULL; | |
| 81 int cert_data_length = i2d_X509(cert, &cert_data); | |
| 82 if (!cert_data_length || !cert_data) { | |
| 83 return false; | |
| 84 } | |
| 85 sp->set(reinterpret_cast<char*>(cert_data), cert_data_length); | |
| 86 return true; | |
| 87 } | |
| 88 | |
| 89 scoped_refptr<X509Certificate> CreateX509Certificate(X509* cert, | |
| 90 STACK_OF(X509) * chain) { | |
| 91 DCHECK(cert); | |
| 92 std::vector<base::StringPiece> der_chain; | |
| 93 base::StringPiece der_cert; | |
| 94 scoped_refptr<X509Certificate> client_cert; | |
| 95 if (!GetX509AsDER(cert, &der_cert)) | |
| 96 return client_cert; | |
| 97 der_chain.push_back(der_cert); | |
| 98 | |
| 99 ScopedX509Stack openssl_chain(X509_chain_up_ref(chain)); | |
| 100 for (size_t i = 0; i < sk_X509_num(openssl_chain.get()); ++i) { | |
| 101 X509* x = sk_X509_value(openssl_chain.get(), i); | |
| 102 if (GetX509AsDER(x, &der_cert)) { | |
| 103 der_chain.push_back(der_cert); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 client_cert = X509Certificate::CreateFromDERCertChain(der_chain); | |
| 108 | |
| 109 for (size_t i = 0; i < der_chain.size(); ++i) { | |
| 110 OPENSSL_free(const_cast<char*>(der_chain[i].data())); | |
| 111 } | |
| 112 if (der_chain.size() - 1 != | |
| 113 static_cast<size_t>(sk_X509_num(openssl_chain.get()))) { | |
| 114 client_cert = NULL; | |
| 115 } | |
| 116 return client_cert; | |
| 117 } | |
| 118 | |
| 119 void DoNothingOnCompletion(int ignore) { | |
| 120 } | |
| 121 | |
| 122 } // namespace | |
| 123 | |
| 23 void EnableSSLServerSockets() { | 124 void EnableSSLServerSockets() { |
| 24 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit(). | 125 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit(). |
| 25 } | 126 } |
| 26 | 127 |
| 27 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( | 128 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( |
| 28 scoped_ptr<StreamSocket> socket, | 129 scoped_ptr<StreamSocket> socket, |
| 29 X509Certificate* certificate, | 130 X509Certificate* certificate, |
| 30 crypto::RSAPrivateKey* key, | 131 crypto::RSAPrivateKey* key, |
| 31 const SSLConfig& ssl_config) { | 132 const SSLConfig& ssl_config) { |
| 32 crypto::EnsureOpenSSLInit(); | 133 crypto::EnsureOpenSSLInit(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 44 transport_recv_eof_(false), | 145 transport_recv_eof_(false), |
| 45 user_read_buf_len_(0), | 146 user_read_buf_len_(0), |
| 46 user_write_buf_len_(0), | 147 user_write_buf_len_(0), |
| 47 transport_write_error_(OK), | 148 transport_write_error_(OK), |
| 48 ssl_(NULL), | 149 ssl_(NULL), |
| 49 transport_bio_(NULL), | 150 transport_bio_(NULL), |
| 50 transport_socket_(transport_socket.Pass()), | 151 transport_socket_(transport_socket.Pass()), |
| 51 ssl_config_(ssl_config), | 152 ssl_config_(ssl_config), |
| 52 cert_(certificate), | 153 cert_(certificate), |
| 53 next_handshake_state_(STATE_NONE), | 154 next_handshake_state_(STATE_NONE), |
| 54 completed_handshake_(false) { | 155 completed_handshake_(false), |
| 156 client_cert_ca_list_(), | |
| 157 client_cert_verifier_(NULL) { | |
| 55 // TODO(byungchul): Need a better way to clone a key. | 158 // TODO(byungchul): Need a better way to clone a key. |
| 56 std::vector<uint8> key_bytes; | 159 std::vector<uint8> key_bytes; |
| 57 CHECK(key->ExportPrivateKey(&key_bytes)); | 160 CHECK(key->ExportPrivateKey(&key_bytes)); |
| 58 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); | 161 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); |
| 59 CHECK(key_.get()); | 162 CHECK(key_.get()); |
| 60 } | 163 } |
| 61 | 164 |
| 62 SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() { | 165 SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() { |
| 63 if (ssl_) { | 166 if (ssl_) { |
| 64 // Calling SSL_shutdown prevents the session from being marked as | 167 // Calling SSL_shutdown prevents the session from being marked as |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 91 rv = DoHandshakeLoop(OK); | 194 rv = DoHandshakeLoop(OK); |
| 92 if (rv == ERR_IO_PENDING) { | 195 if (rv == ERR_IO_PENDING) { |
| 93 user_handshake_callback_ = callback; | 196 user_handshake_callback_ = callback; |
| 94 } else { | 197 } else { |
| 95 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv); | 198 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv); |
| 96 } | 199 } |
| 97 | 200 |
| 98 return rv > OK ? OK : rv; | 201 return rv > OK ? OK : rv; |
| 99 } | 202 } |
| 100 | 203 |
| 204 void SSLServerSocketOpenSSL::SetAllowClientCert(bool allow_client_cert) { | |
| 205 ssl_config_.send_client_cert = allow_client_cert; | |
| 206 } | |
| 207 | |
| 208 void SSLServerSocketOpenSSL::SetClientCertCAList( | |
| 209 const CertificateList& client_cert_ca_list) { | |
| 210 client_cert_ca_list_ = client_cert_ca_list; | |
| 211 } | |
| 212 | |
| 213 void SSLServerSocketOpenSSL::SetClientCertVerifier( | |
| 214 CertVerifier* client_cert_verifier) { | |
| 215 client_cert_verifier_ = client_cert_verifier; | |
| 216 } | |
| 217 | |
| 101 int SSLServerSocketOpenSSL::ExportKeyingMaterial( | 218 int SSLServerSocketOpenSSL::ExportKeyingMaterial( |
| 102 const base::StringPiece& label, | 219 const base::StringPiece& label, |
| 103 bool has_context, | 220 bool has_context, |
| 104 const base::StringPiece& context, | 221 const base::StringPiece& context, |
| 105 unsigned char* out, | 222 unsigned char* out, |
| 106 unsigned int outlen) { | 223 unsigned int outlen) { |
| 107 if (!IsConnected()) | 224 if (!IsConnected()) |
| 108 return ERR_SOCKET_NOT_CONNECTED; | 225 return ERR_SOCKET_NOT_CONNECTED; |
| 109 | 226 |
| 110 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 227 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 NOTIMPLEMENTED(); | 353 NOTIMPLEMENTED(); |
| 237 return false; | 354 return false; |
| 238 } | 355 } |
| 239 | 356 |
| 240 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const { | 357 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const { |
| 241 // NPN is not supported by this class. | 358 // NPN is not supported by this class. |
| 242 return kProtoUnknown; | 359 return kProtoUnknown; |
| 243 } | 360 } |
| 244 | 361 |
| 245 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { | 362 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { |
| 246 NOTIMPLEMENTED(); | 363 ssl_info->Reset(); |
| 247 return false; | 364 if (!completed_handshake_) { |
| 365 return false; | |
| 366 } | |
| 367 ExtractClientCert(); | |
| 368 ssl_info->cert = client_cert_; | |
| 369 ssl_info->client_cert_sent = | |
| 370 ssl_config_.send_client_cert && client_cert_.get(); | |
| 371 | |
| 372 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_); | |
| 373 CHECK(cipher); | |
| 374 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL); | |
| 375 | |
| 376 ssl_info->connection_status = | |
| 377 EncodeSSLConnectionStatus(SSL_CIPHER_get_id(cipher), | |
| 378 0 /* no compression */, GetNetSSLVersion(ssl_)); | |
| 379 | |
| 380 if (!SSL_get_secure_renegotiation_support(ssl_)) | |
| 381 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; | |
| 382 | |
| 383 if (ssl_config_.version_fallback) | |
| 384 ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK; | |
| 385 | |
| 386 ssl_info->handshake_type = SSL_session_reused(ssl_) | |
| 387 ? SSLInfo::HANDSHAKE_RESUME | |
| 388 : SSLInfo::HANDSHAKE_FULL; | |
| 389 | |
|
Ryan Sleevi
2015/03/19 04:38:25
Much more readable construction ;)
| |
| 390 return true; | |
| 248 } | 391 } |
| 249 | 392 |
| 250 void SSLServerSocketOpenSSL::OnSendComplete(int result) { | 393 void SSLServerSocketOpenSSL::OnSendComplete(int result) { |
| 251 if (next_handshake_state_ == STATE_HANDSHAKE) { | 394 if (next_handshake_state_ == STATE_HANDSHAKE) { |
| 252 // In handshake phase. | 395 // In handshake phase. |
| 253 OnHandshakeIOComplete(result); | 396 OnHandshakeIOComplete(result); |
| 254 return; | 397 return; |
| 255 } | 398 } |
| 256 | 399 |
| 257 // TODO(byungchul): This state machine is not correct. Copy the state machine | 400 // TODO(byungchul): This state machine is not correct. Copy the state machine |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 int net_error = OK; | 699 int net_error = OK; |
| 557 int rv = SSL_do_handshake(ssl_); | 700 int rv = SSL_do_handshake(ssl_); |
| 558 | 701 |
| 559 if (rv == 1) { | 702 if (rv == 1) { |
| 560 completed_handshake_ = true; | 703 completed_handshake_ = true; |
| 561 } else { | 704 } else { |
| 562 int ssl_error = SSL_get_error(ssl_, rv); | 705 int ssl_error = SSL_get_error(ssl_, rv); |
| 563 OpenSSLErrorInfo error_info; | 706 OpenSSLErrorInfo error_info; |
| 564 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); | 707 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); |
| 565 | 708 |
| 709 // This hack is necessary because the mapping of SSL error codes to | |
| 710 // net_errors assumes (correctly for client sockets, but erroneously for | |
| 711 // server sockets) that peer cert verification failure can only occur if | |
| 712 // the cert changed during a renego. | |
| 713 if (net_error == ERR_SSL_SERVER_CERT_CHANGED) | |
| 714 net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT; | |
| 715 | |
| 566 // If not done, stay in this state | 716 // If not done, stay in this state |
| 567 if (net_error == ERR_IO_PENDING) { | 717 if (net_error == ERR_IO_PENDING) { |
| 568 GotoState(STATE_HANDSHAKE); | 718 GotoState(STATE_HANDSHAKE); |
| 569 } else { | 719 } else { |
| 570 LOG(ERROR) << "handshake failed; returned " << rv | 720 LOG(ERROR) << "handshake failed; returned " << rv |
| 571 << ", SSL error code " << ssl_error | 721 << ", SSL error code " << ssl_error |
| 572 << ", net_error " << net_error; | 722 << ", net_error " << net_error; |
| 573 net_log_.AddEvent( | 723 net_log_.AddEvent( |
| 574 NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 724 NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 575 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); | 725 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 601 ResetAndReturn(&user_write_callback_).Run(rv); | 751 ResetAndReturn(&user_write_callback_).Run(rv); |
| 602 } | 752 } |
| 603 | 753 |
| 604 int SSLServerSocketOpenSSL::Init() { | 754 int SSLServerSocketOpenSSL::Init() { |
| 605 DCHECK(!ssl_); | 755 DCHECK(!ssl_); |
| 606 DCHECK(!transport_bio_); | 756 DCHECK(!transport_bio_); |
| 607 | 757 |
| 608 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 758 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 609 | 759 |
| 610 ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method())); | 760 ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method())); |
| 761 SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), CertVerifyCallback, this); | |
| 611 ssl_ = SSL_new(ssl_ctx.get()); | 762 ssl_ = SSL_new(ssl_ctx.get()); |
| 612 if (!ssl_) | 763 if (!ssl_) |
| 613 return ERR_UNEXPECTED; | 764 return ERR_UNEXPECTED; |
| 614 | 765 |
| 615 BIO* ssl_bio = NULL; | 766 BIO* ssl_bio = NULL; |
| 616 // 0 => use default buffer sizes. | 767 // 0 => use default buffer sizes. |
| 617 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 768 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
| 618 return ERR_UNEXPECTED; | 769 return ERR_UNEXPECTED; |
| 619 DCHECK(ssl_bio); | 770 DCHECK(ssl_bio); |
| 620 DCHECK(transport_bio_); | 771 DCHECK(transport_bio_); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 SSL_clear_options(ssl_, options.clear_mask); | 829 SSL_clear_options(ssl_, options.clear_mask); |
| 679 | 830 |
| 680 // Same as above, this time for the SSL mode. | 831 // Same as above, this time for the SSL mode. |
| 681 SslSetClearMask mode; | 832 SslSetClearMask mode; |
| 682 | 833 |
| 683 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); | 834 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); |
| 684 | 835 |
| 685 SSL_set_mode(ssl_, mode.set_mask); | 836 SSL_set_mode(ssl_, mode.set_mask); |
| 686 SSL_clear_mode(ssl_, mode.clear_mask); | 837 SSL_clear_mode(ssl_, mode.clear_mask); |
| 687 | 838 |
| 839 if (ssl_config_.send_client_cert) { | |
| 840 ssl_->verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; | |
| 841 if (client_cert_verifier_) | |
| 842 ssl_->verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; | |
| 843 if (!client_cert_ca_list_.empty()) { | |
| 844 ScopedX509NameStack stack(sk_X509_NAME_new_null()); | |
| 845 for (CertificateList::iterator it = client_cert_ca_list_.begin(); | |
|
Ryan Sleevi
2015/03/19 04:38:25
for (const auto& certificate : client_cert_ca_list
| |
| 846 it != client_cert_ca_list_.end(); it++) { | |
| 847 X509* ca_cert = it->get()->os_cert_handle(); | |
| 848 ScopedX509Name subj(X509_NAME_dup(ca_cert->cert_info->subject)); | |
| 849 sk_X509_NAME_push(stack.get(), subj.release()); | |
| 850 } | |
| 851 SSL_set_client_CA_list(ssl_, stack.release()); | |
| 852 } | |
| 853 } | |
| 854 | |
| 688 return OK; | 855 return OK; |
| 689 } | 856 } |
| 690 | 857 |
| 858 void SSLServerSocketOpenSSL::ExtractClientCert() { | |
| 859 if (client_cert_.get() || !completed_handshake_) { | |
| 860 return; | |
| 861 } | |
| 862 X509* cert = SSL_get_peer_certificate(ssl_); | |
| 863 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); | |
| 864 client_cert_ = CreateX509Certificate(cert, chain); | |
| 865 } | |
| 866 | |
| 867 // static | |
| 868 int SSLServerSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx, | |
| 869 void* arg) { | |
| 870 SSLServerSocketOpenSSL* self = reinterpret_cast<SSLServerSocketOpenSSL*>(arg); | |
| 871 DCHECK(self); | |
| 872 if (!self->client_cert_verifier_) | |
| 873 return 1; | |
| 874 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( | |
| 875 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); | |
| 876 DCHECK(ssl); | |
| 877 X509* x = store_ctx->cert; | |
| 878 STACK_OF(X509)* chain = store_ctx->chain; | |
| 879 scoped_refptr<X509Certificate> client_cert(CreateX509Certificate(x, chain)); | |
| 880 | |
| 881 CertVerifyResult ignore_result; | |
| 882 CertVerifier::RequestHandle ignore_handle; | |
| 883 int res = self->client_cert_verifier_->Verify( | |
| 884 client_cert.get(), std::string(), 0, NULL, &ignore_result, | |
| 885 base::Bind(&DoNothingOnCompletion), &ignore_handle, self->net_log_); | |
| 886 if (res == OK) { | |
| 887 self->client_cert_ = client_cert; | |
| 888 return 1; | |
| 889 } else { | |
| 890 X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED); | |
| 891 return 0; | |
| 892 } | |
| 893 } | |
| 894 | |
| 691 } // namespace net | 895 } // namespace net |
| OLD | NEW |