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 |