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_verifier.h" |
| 18 #include "net/cert/cert_verify_result.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 // TODO(dougsteed) These definitions copied from ssl_client_socket_openssl.cc. |
| 31 // Might want to consider putting them in a common place. |
| 32 void FreeX509Stack(STACK_OF(X509) * ptr) { |
| 33 sk_X509_pop_free(ptr, X509_free); |
| 34 } |
| 35 |
| 36 void FreeX509NameStack(STACK_OF(X509_NAME) * ptr) { |
| 37 sk_X509_NAME_pop_free(ptr, X509_NAME_free); |
| 38 } |
| 39 |
| 40 typedef crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free> ScopedX509Name; |
| 41 typedef crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack> ScopedX509Stack; |
| 42 typedef crypto::ScopedOpenSSL<STACK_OF(X509_NAME), FreeX509NameStack> |
| 43 ScopedX509NameStack; |
| 44 |
| 45 #if OPENSSL_VERSION_NUMBER < 0x1000103fL |
| 46 // This method doesn't seem to have made it into the OpenSSL headers. |
| 47 unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { |
| 48 return cipher->id; |
| 49 } |
| 50 #endif |
| 51 |
| 52 // Used for encoding the |connection_status| field of an SSLInfo object. |
| 53 int EncodeSSLConnectionStatus(int cipher_suite, int compression, int version) { |
| 54 return (cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) | |
| 55 ((compression & SSL_CONNECTION_COMPRESSION_MASK) |
| 56 << SSL_CONNECTION_COMPRESSION_SHIFT) | |
| 57 ((version & SSL_CONNECTION_VERSION_MASK) |
| 58 << SSL_CONNECTION_VERSION_SHIFT); |
| 59 } |
| 60 |
| 61 // Returns the net SSL version number (see ssl_connection_status_flags.h) for |
| 62 // this SSL connection. |
| 63 int GetNetSSLVersion(SSL* ssl) { |
| 64 switch (SSL_version(ssl)) { |
| 65 case SSL2_VERSION: |
| 66 return SSL_CONNECTION_VERSION_SSL2; |
| 67 case SSL3_VERSION: |
| 68 return SSL_CONNECTION_VERSION_SSL3; |
| 69 case TLS1_VERSION: |
| 70 return SSL_CONNECTION_VERSION_TLS1; |
| 71 case 0x0302: |
| 72 return SSL_CONNECTION_VERSION_TLS1_1; |
| 73 case 0x0303: |
| 74 return SSL_CONNECTION_VERSION_TLS1_2; |
| 75 default: |
| 76 return SSL_CONNECTION_VERSION_UNKNOWN; |
| 77 } |
| 78 } |
| 79 |
| 80 bool GetX509AsDER(X509* cert, base::StringPiece* sp) { |
| 81 unsigned char* cert_data = NULL; |
| 82 int cert_data_length = i2d_X509(cert, &cert_data); |
| 83 if (!cert_data_length || !cert_data) { |
| 84 return false; |
| 85 } |
| 86 sp->set(reinterpret_cast<char*>(cert_data), cert_data_length); |
| 87 return true; |
| 88 } |
| 89 |
| 90 scoped_refptr<X509Certificate> CreateX509Certificate(X509* cert, |
| 91 STACK_OF(X509) * chain) { |
| 92 DCHECK(cert); |
| 93 std::vector<base::StringPiece> der_chain; |
| 94 base::StringPiece der_cert; |
| 95 scoped_refptr<X509Certificate> client_cert; |
| 96 if (!GetX509AsDER(cert, &der_cert)) |
| 97 return client_cert; |
| 98 der_chain.push_back(der_cert); |
| 99 |
| 100 ScopedX509Stack openssl_chain(X509_chain_up_ref(chain)); |
| 101 for (size_t i = 0; i < sk_X509_num(openssl_chain.get()); ++i) { |
| 102 X509* x = sk_X509_value(openssl_chain.get(), i); |
| 103 if (GetX509AsDER(x, &der_cert)) { |
| 104 der_chain.push_back(der_cert); |
| 105 } |
| 106 } |
| 107 |
| 108 client_cert = X509Certificate::CreateFromDERCertChain(der_chain); |
| 109 |
| 110 for (size_t i = 0; i < der_chain.size(); ++i) { |
| 111 OPENSSL_free(const_cast<char*>(der_chain[i].data())); |
| 112 } |
| 113 if (der_chain.size() - 1 != |
| 114 static_cast<size_t>(sk_X509_num(openssl_chain.get()))) { |
| 115 client_cert = NULL; |
| 116 } |
| 117 return client_cert; |
| 118 } |
| 119 |
| 120 void DoNothingOnCompletion(int ignore) {} |
| 121 |
| 122 ScopedX509 OSCertHandleToOpenSSL(X509Certificate::OSCertHandle os_handle) { |
| 123 #if defined(USE_OPENSSL_CERTS) |
| 124 return ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); |
| 125 #else |
| 126 std::string der_encoded; |
| 127 if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded)) |
| 128 return ScopedX509(); |
| 129 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); |
| 130 return ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size())); |
| 131 #endif |
| 132 } |
| 133 |
| 134 } // namespace |
| 135 |
24 void EnableSSLServerSockets() { | 136 void EnableSSLServerSockets() { |
25 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit(). | 137 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit(). |
26 } | 138 } |
27 | 139 |
28 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( | 140 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( |
29 scoped_ptr<StreamSocket> socket, | 141 scoped_ptr<StreamSocket> socket, |
30 X509Certificate* certificate, | 142 X509Certificate* certificate, |
31 crypto::RSAPrivateKey* key, | 143 crypto::RSAPrivateKey* key, |
32 const SSLServerConfig& ssl_config) { | 144 const SSLServerConfig& ssl_config) { |
33 crypto::EnsureOpenSSLInit(); | 145 crypto::EnsureOpenSSLInit(); |
(...skipping 11 matching lines...) Expand all Loading... |
45 transport_recv_eof_(false), | 157 transport_recv_eof_(false), |
46 user_read_buf_len_(0), | 158 user_read_buf_len_(0), |
47 user_write_buf_len_(0), | 159 user_write_buf_len_(0), |
48 transport_write_error_(OK), | 160 transport_write_error_(OK), |
49 ssl_(NULL), | 161 ssl_(NULL), |
50 transport_bio_(NULL), | 162 transport_bio_(NULL), |
51 transport_socket_(transport_socket.Pass()), | 163 transport_socket_(transport_socket.Pass()), |
52 ssl_config_(ssl_config), | 164 ssl_config_(ssl_config), |
53 cert_(certificate), | 165 cert_(certificate), |
54 next_handshake_state_(STATE_NONE), | 166 next_handshake_state_(STATE_NONE), |
55 completed_handshake_(false) { | 167 completed_handshake_(false), |
| 168 client_cert_ca_list_(), |
| 169 client_cert_verifier_(NULL) { |
56 // TODO(byungchul): Need a better way to clone a key. | 170 // TODO(byungchul): Need a better way to clone a key. |
57 std::vector<uint8> key_bytes; | 171 std::vector<uint8> key_bytes; |
58 CHECK(key->ExportPrivateKey(&key_bytes)); | 172 CHECK(key->ExportPrivateKey(&key_bytes)); |
59 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); | 173 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); |
60 CHECK(key_.get()); | 174 CHECK(key_.get()); |
61 } | 175 } |
62 | 176 |
63 SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() { | 177 SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() { |
64 if (ssl_) { | 178 if (ssl_) { |
65 // Calling SSL_shutdown prevents the session from being marked as | 179 // Calling SSL_shutdown prevents the session from being marked as |
(...skipping 26 matching lines...) Expand all Loading... |
92 rv = DoHandshakeLoop(OK); | 206 rv = DoHandshakeLoop(OK); |
93 if (rv == ERR_IO_PENDING) { | 207 if (rv == ERR_IO_PENDING) { |
94 user_handshake_callback_ = callback; | 208 user_handshake_callback_ = callback; |
95 } else { | 209 } else { |
96 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv); | 210 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv); |
97 } | 211 } |
98 | 212 |
99 return rv > OK ? OK : rv; | 213 return rv > OK ? OK : rv; |
100 } | 214 } |
101 | 215 |
| 216 void SSLServerSocketOpenSSL::SetRequireClientCert(bool require_client_cert) { |
| 217 ssl_config_.require_client_cert = require_client_cert; |
| 218 } |
| 219 |
| 220 void SSLServerSocketOpenSSL::SetClientCertCAList( |
| 221 const CertificateList& client_cert_ca_list) { |
| 222 client_cert_ca_list_ = client_cert_ca_list; |
| 223 } |
| 224 |
| 225 void SSLServerSocketOpenSSL::SetClientCertVerifier( |
| 226 CertVerifier* client_cert_verifier) { |
| 227 client_cert_verifier_ = client_cert_verifier; |
| 228 } |
| 229 |
102 int SSLServerSocketOpenSSL::ExportKeyingMaterial( | 230 int SSLServerSocketOpenSSL::ExportKeyingMaterial( |
103 const base::StringPiece& label, | 231 const base::StringPiece& label, |
104 bool has_context, | 232 bool has_context, |
105 const base::StringPiece& context, | 233 const base::StringPiece& context, |
106 unsigned char* out, | 234 unsigned char* out, |
107 unsigned int outlen) { | 235 unsigned int outlen) { |
108 if (!IsConnected()) | 236 if (!IsConnected()) |
109 return ERR_SOCKET_NOT_CONNECTED; | 237 return ERR_SOCKET_NOT_CONNECTED; |
110 | 238 |
111 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 239 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 NOTIMPLEMENTED(); | 365 NOTIMPLEMENTED(); |
238 return false; | 366 return false; |
239 } | 367 } |
240 | 368 |
241 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const { | 369 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const { |
242 // NPN is not supported by this class. | 370 // NPN is not supported by this class. |
243 return kProtoUnknown; | 371 return kProtoUnknown; |
244 } | 372 } |
245 | 373 |
246 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { | 374 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { |
247 NOTIMPLEMENTED(); | 375 ssl_info->Reset(); |
248 return false; | 376 if (!completed_handshake_) { |
| 377 return false; |
| 378 } |
| 379 ExtractClientCert(); |
| 380 ssl_info->cert = client_cert_; |
| 381 ssl_info->client_cert_sent = |
| 382 ssl_config_.require_client_cert && client_cert_.get(); |
| 383 |
| 384 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_); |
| 385 CHECK(cipher); |
| 386 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL); |
| 387 |
| 388 ssl_info->connection_status = |
| 389 EncodeSSLConnectionStatus(SSL_CIPHER_get_id(cipher), |
| 390 0 /* no compression */, GetNetSSLVersion(ssl_)); |
| 391 |
| 392 if (!SSL_get_secure_renegotiation_support(ssl_)) |
| 393 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; |
| 394 |
| 395 ssl_info->handshake_type = SSL_session_reused(ssl_) |
| 396 ? SSLInfo::HANDSHAKE_RESUME |
| 397 : SSLInfo::HANDSHAKE_FULL; |
| 398 |
| 399 return true; |
249 } | 400 } |
250 | 401 |
251 void SSLServerSocketOpenSSL::GetConnectionAttempts( | 402 void SSLServerSocketOpenSSL::GetConnectionAttempts( |
252 ConnectionAttempts* out) const { | 403 ConnectionAttempts* out) const { |
253 out->clear(); | 404 out->clear(); |
254 } | 405 } |
255 | 406 |
256 int64_t SSLServerSocketOpenSSL::GetTotalReceivedBytes() const { | 407 int64_t SSLServerSocketOpenSSL::GetTotalReceivedBytes() const { |
257 return transport_socket_->GetTotalReceivedBytes(); | 408 return transport_socket_->GetTotalReceivedBytes(); |
258 } | 409 } |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 int net_error = OK; | 717 int net_error = OK; |
567 int rv = SSL_do_handshake(ssl_); | 718 int rv = SSL_do_handshake(ssl_); |
568 | 719 |
569 if (rv == 1) { | 720 if (rv == 1) { |
570 completed_handshake_ = true; | 721 completed_handshake_ = true; |
571 } else { | 722 } else { |
572 int ssl_error = SSL_get_error(ssl_, rv); | 723 int ssl_error = SSL_get_error(ssl_, rv); |
573 OpenSSLErrorInfo error_info; | 724 OpenSSLErrorInfo error_info; |
574 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); | 725 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); |
575 | 726 |
| 727 // This hack is necessary because the mapping of SSL error codes to |
| 728 // net_errors assumes (correctly for client sockets, but erroneously for |
| 729 // server sockets) that peer cert verification failure can only occur if |
| 730 // the cert changed during a renego. |
| 731 if (net_error == ERR_SSL_SERVER_CERT_CHANGED) |
| 732 net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT; |
| 733 |
576 // If not done, stay in this state | 734 // If not done, stay in this state |
577 if (net_error == ERR_IO_PENDING) { | 735 if (net_error == ERR_IO_PENDING) { |
578 GotoState(STATE_HANDSHAKE); | 736 GotoState(STATE_HANDSHAKE); |
579 } else { | 737 } else { |
580 LOG(ERROR) << "handshake failed; returned " << rv | 738 LOG(ERROR) << "handshake failed; returned " << rv |
581 << ", SSL error code " << ssl_error | 739 << ", SSL error code " << ssl_error |
582 << ", net_error " << net_error; | 740 << ", net_error " << net_error; |
583 net_log_.AddEvent( | 741 net_log_.AddEvent( |
584 NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 742 NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
585 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); | 743 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); |
(...skipping 25 matching lines...) Expand all Loading... |
611 ResetAndReturn(&user_write_callback_).Run(rv); | 769 ResetAndReturn(&user_write_callback_).Run(rv); |
612 } | 770 } |
613 | 771 |
614 int SSLServerSocketOpenSSL::Init() { | 772 int SSLServerSocketOpenSSL::Init() { |
615 DCHECK(!ssl_); | 773 DCHECK(!ssl_); |
616 DCHECK(!transport_bio_); | 774 DCHECK(!transport_bio_); |
617 | 775 |
618 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 776 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
619 | 777 |
620 ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method())); | 778 ScopedSSL_CTX ssl_ctx(SSL_CTX_new(SSLv23_server_method())); |
621 | |
622 if (ssl_config_.require_client_cert) | 779 if (ssl_config_.require_client_cert) |
623 SSL_CTX_set_verify(ssl_ctx.get(), SSL_VERIFY_PEER, NULL); | 780 SSL_CTX_set_verify(ssl_ctx.get(), SSL_VERIFY_PEER, NULL); |
624 | 781 SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), CertVerifyCallback, this); |
625 ssl_ = SSL_new(ssl_ctx.get()); | 782 ssl_ = SSL_new(ssl_ctx.get()); |
626 if (!ssl_) | 783 if (!ssl_) |
627 return ERR_UNEXPECTED; | 784 return ERR_UNEXPECTED; |
628 | 785 |
629 BIO* ssl_bio = NULL; | 786 BIO* ssl_bio = NULL; |
630 // 0 => use default buffer sizes. | 787 // 0 => use default buffer sizes. |
631 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 788 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
632 return ERR_UNEXPECTED; | 789 return ERR_UNEXPECTED; |
633 DCHECK(ssl_bio); | 790 DCHECK(ssl_bio); |
634 DCHECK(transport_bio_); | 791 DCHECK(transport_bio_); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 } | 864 } |
708 } | 865 } |
709 | 866 |
710 int rv = SSL_set_cipher_list(ssl_, command.c_str()); | 867 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. | 868 // 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 | 869 // 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. | 870 // handshake at which point the appropriate error is bubbled up to the client. |
714 LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command | 871 LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command |
715 << "') returned " << rv; | 872 << "') returned " << rv; |
716 | 873 |
| 874 if (ssl_config_.require_client_cert) { |
| 875 if (client_cert_verifier_) |
| 876 ssl_->verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; |
| 877 if (!client_cert_ca_list_.empty()) { |
| 878 ScopedX509NameStack stack(sk_X509_NAME_new_null()); |
| 879 for (CertificateList::iterator it = client_cert_ca_list_.begin(); |
| 880 it != client_cert_ca_list_.end(); it++) { |
| 881 ScopedX509 ca_cert = OSCertHandleToOpenSSL(it->get()->os_cert_handle()); |
| 882 ScopedX509Name subj(X509_NAME_dup(ca_cert->cert_info->subject)); |
| 883 sk_X509_NAME_push(stack.get(), subj.release()); |
| 884 } |
| 885 SSL_set_client_CA_list(ssl_, stack.release()); |
| 886 } |
| 887 } |
| 888 |
717 return OK; | 889 return OK; |
718 } | 890 } |
719 | 891 |
| 892 void SSLServerSocketOpenSSL::ExtractClientCert() { |
| 893 if (client_cert_.get() || !completed_handshake_) { |
| 894 return; |
| 895 } |
| 896 X509* cert = SSL_get_peer_certificate(ssl_); |
| 897 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); |
| 898 client_cert_ = CreateX509Certificate(cert, chain); |
| 899 } |
| 900 |
| 901 // static |
| 902 int SSLServerSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx, |
| 903 void* arg) { |
| 904 SSLServerSocketOpenSSL* self = reinterpret_cast<SSLServerSocketOpenSSL*>(arg); |
| 905 DCHECK(self); |
| 906 if (!self->client_cert_verifier_) |
| 907 return 1; |
| 908 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( |
| 909 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); |
| 910 DCHECK(ssl); |
| 911 X509* x = store_ctx->cert; |
| 912 STACK_OF(X509)* chain = store_ctx->chain; |
| 913 scoped_refptr<X509Certificate> client_cert(CreateX509Certificate(x, chain)); |
| 914 |
| 915 CertVerifyResult ignore_result; |
| 916 scoped_ptr<CertVerifier::Request> ignore_async; |
| 917 int res = self->client_cert_verifier_->Verify( |
| 918 client_cert.get(), std::string(), std::string(), 0, NULL, &ignore_result, |
| 919 base::Bind(&DoNothingOnCompletion), &ignore_async, self->net_log_); |
| 920 if (res == OK) { |
| 921 self->client_cert_ = client_cert; |
| 922 return 1; |
| 923 } else { |
| 924 X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_CERT_REJECTED); |
| 925 return 0; |
| 926 } |
| 927 } |
| 928 |
720 } // namespace net | 929 } // namespace net |
OLD | NEW |