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

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: Passing this CL to RyanChung for further work. Created 5 years, 1 month 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
« no previous file with comments | « net/socket/ssl_server_socket_openssl.h ('k') | net/socket/ssl_server_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/socket/ssl_server_socket_openssl.h ('k') | net/socket/ssl_server_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698