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

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

Issue 994743003: Support for client certs in ssl_server_socket. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
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 #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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698