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

Side by Side Diff: net/socket/ssl_server_socket_nss.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_nss.h" 5 #include "net/socket/ssl_server_socket_nss.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <winsock2.h> 8 #include <winsock2.h>
9 #endif 9 #endif
10 10
(...skipping 19 matching lines...) Expand all
30 #include <limits> 30 #include <limits>
31 31
32 #include "base/callback_helpers.h" 32 #include "base/callback_helpers.h"
33 #include "base/lazy_instance.h" 33 #include "base/lazy_instance.h"
34 #include "base/memory/ref_counted.h" 34 #include "base/memory/ref_counted.h"
35 #include "crypto/rsa_private_key.h" 35 #include "crypto/rsa_private_key.h"
36 #include "crypto/nss_util_internal.h" 36 #include "crypto/nss_util_internal.h"
37 #include "net/base/io_buffer.h" 37 #include "net/base/io_buffer.h"
38 #include "net/base/net_errors.h" 38 #include "net/base/net_errors.h"
39 #include "net/base/net_log.h" 39 #include "net/base/net_log.h"
40 #include "net/cert/cert_verifier.h"
41 #include "net/cert/cert_verify_result.h"
40 #include "net/socket/nss_ssl_util.h" 42 #include "net/socket/nss_ssl_util.h"
43 #include "net/ssl/ssl_connection_status_flags.h"
44 #include "net/ssl/ssl_info.h"
41 45
42 // SSL plaintext fragments are shorter than 16KB. Although the record layer 46 // SSL plaintext fragments are shorter than 16KB. Although the record layer
43 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much 47 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
44 // smaller than 1KB. So a 17KB buffer should be large enough to hold an 48 // smaller than 1KB. So a 17KB buffer should be large enough to hold an
45 // entire SSL record. 49 // entire SSL record.
46 static const int kRecvBufferSize = 17 * 1024; 50 static const int kRecvBufferSize = 17 * 1024;
47 static const int kSendBufferSize = 17 * 1024; 51 static const int kSendBufferSize = 17 * 1024;
48 52
49 #define GotoState(s) next_handshake_state_ = s 53 #define GotoState(s) next_handshake_state_ = s
50 54
(...skipping 11 matching lines...) Expand all
62 SSL_ConfigServerSessionIDCache(64, 28800, 28800, NULL); 66 SSL_ConfigServerSessionIDCache(64, 28800, 28800, NULL);
63 g_nss_server_sockets_init = true; 67 g_nss_server_sockets_init = true;
64 } 68 }
65 69
66 ~NSSSSLServerInitSingleton() { 70 ~NSSSSLServerInitSingleton() {
67 SSL_ShutdownServerSessionIDCache(); 71 SSL_ShutdownServerSessionIDCache();
68 g_nss_server_sockets_init = false; 72 g_nss_server_sockets_init = false;
69 } 73 }
70 }; 74 };
71 75
76 void DoNothingOnCompletion(int ignore) {
77 }
78
72 static base::LazyInstance<NSSSSLServerInitSingleton> 79 static base::LazyInstance<NSSSSLServerInitSingleton>
73 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER; 80 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
74 81
75 } // namespace 82 } // namespace
76 83
77 void EnableSSLServerSockets() { 84 void EnableSSLServerSockets() {
78 g_nss_ssl_server_init_singleton.Get(); 85 g_nss_ssl_server_init_singleton.Get();
79 } 86 }
80 87
81 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( 88 scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
82 scoped_ptr<StreamSocket> socket, 89 scoped_ptr<StreamSocket> socket,
83 X509Certificate* cert, 90 X509Certificate* certificate,
84 crypto::RSAPrivateKey* key, 91 crypto::RSAPrivateKey* key,
85 const SSLConfig& ssl_config) { 92 const SSLConfig& ssl_config) {
86 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been" 93 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
87 << " called yet!"; 94 << " called yet!";
88 95
89 return scoped_ptr<SSLServerSocket>( 96 return scoped_ptr<SSLServerSocket>(
90 new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config)); 97 new SSLServerSocketNSS(socket.Pass(), certificate, key, ssl_config));
91 } 98 }
92 99
93 SSLServerSocketNSS::SSLServerSocketNSS( 100 SSLServerSocketNSS::SSLServerSocketNSS(
94 scoped_ptr<StreamSocket> transport_socket, 101 scoped_ptr<StreamSocket> transport_socket,
95 scoped_refptr<X509Certificate> cert, 102 scoped_refptr<X509Certificate> cert,
96 crypto::RSAPrivateKey* key, 103 crypto::RSAPrivateKey* key,
97 const SSLConfig& ssl_config) 104 const SSLConfig& ssl_config)
98 : transport_send_busy_(false), 105 : transport_send_busy_(false),
99 transport_recv_busy_(false), 106 transport_recv_busy_(false),
100 user_read_buf_len_(0), 107 user_read_buf_len_(0),
101 user_write_buf_len_(0), 108 user_write_buf_len_(0),
102 nss_fd_(NULL), 109 nss_fd_(NULL),
103 nss_bufs_(NULL), 110 nss_bufs_(NULL),
104 transport_socket_(transport_socket.Pass()), 111 transport_socket_(transport_socket.Pass()),
105 ssl_config_(ssl_config), 112 ssl_config_(ssl_config),
106 cert_(cert), 113 cert_(cert),
107 next_handshake_state_(STATE_NONE), 114 next_handshake_state_(STATE_NONE),
108 completed_handshake_(false) { 115 completed_handshake_(false),
116 client_cert_ca_list_(),
117 client_cert_verifier_(NULL) {
109 // TODO(hclam): Need a better way to clone a key. 118 // TODO(hclam): Need a better way to clone a key.
110 std::vector<uint8> key_bytes; 119 std::vector<uint8> key_bytes;
111 CHECK(key->ExportPrivateKey(&key_bytes)); 120 CHECK(key->ExportPrivateKey(&key_bytes));
112 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); 121 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
113 CHECK(key_.get()); 122 CHECK(key_.get());
114 } 123 }
115 124
116 SSLServerSocketNSS::~SSLServerSocketNSS() { 125 SSLServerSocketNSS::~SSLServerSocketNSS() {
117 if (nss_fd_ != NULL) { 126 if (nss_fd_ != NULL) {
118 PR_Close(nss_fd_); 127 PR_Close(nss_fd_);
(...skipping 28 matching lines...) Expand all
147 rv = DoHandshakeLoop(OK); 156 rv = DoHandshakeLoop(OK);
148 if (rv == ERR_IO_PENDING) { 157 if (rv == ERR_IO_PENDING) {
149 user_handshake_callback_ = callback; 158 user_handshake_callback_ = callback;
150 } else { 159 } else {
151 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv); 160 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
152 } 161 }
153 162
154 return rv > OK ? OK : rv; 163 return rv > OK ? OK : rv;
155 } 164 }
156 165
166 void SSLServerSocketNSS::SetAllowClientCert(bool allow_client_cert) {
167 ssl_config_.send_client_cert = allow_client_cert;
168 }
169
170 void SSLServerSocketNSS::SetClientCertCAList(
171 const CertificateList& client_cert_ca_list) {
172 client_cert_ca_list_ = client_cert_ca_list;
173 }
174
175 void SSLServerSocketNSS::SetClientCertVerifier(
176 CertVerifier* client_cert_verifier) {
177 client_cert_verifier_ = client_cert_verifier;
178 }
179
157 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label, 180 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
158 bool has_context, 181 bool has_context,
159 const base::StringPiece& context, 182 const base::StringPiece& context,
160 unsigned char* out, 183 unsigned char* out,
161 unsigned int outlen) { 184 unsigned int outlen) {
162 if (!IsConnected()) 185 if (!IsConnected())
163 return ERR_SOCKET_NOT_CONNECTED; 186 return ERR_SOCKET_NOT_CONNECTED;
164 SECStatus result = SSL_ExportKeyingMaterial( 187 SECStatus result = SSL_ExportKeyingMaterial(
165 nss_fd_, label.data(), label.size(), has_context, 188 nss_fd_, label.data(), label.size(), has_context,
166 reinterpret_cast<const unsigned char*>(context.data()), 189 reinterpret_cast<const unsigned char*>(context.data()),
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 bool SSLServerSocketNSS::WasNpnNegotiated() const { 318 bool SSLServerSocketNSS::WasNpnNegotiated() const {
296 NOTIMPLEMENTED(); 319 NOTIMPLEMENTED();
297 return false; 320 return false;
298 } 321 }
299 322
300 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const { 323 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
301 // NPN is not supported by this class. 324 // NPN is not supported by this class.
302 return kProtoUnknown; 325 return kProtoUnknown;
303 } 326 }
304 327
305 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { 328 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
Ryan Sleevi 2015/03/19 04:38:25 I'm vaguely uncomfortable with overloading SSLInfo
306 NOTIMPLEMENTED(); 329 ssl_info->Reset();
307 return false; 330 if (!completed_handshake_) {
331 return false;
332 }
Ryan Sleevi 2015/03/19 04:38:25 No braces
333 ExtractClientCert();
334 ssl_info->cert = client_cert_;
335 UpdateSSLConnectionStatus(nss_fd_, ssl_config_, &ssl_info->connection_status);
336 ssl_info->client_cert_sent = client_cert_.get() ? true : false;
Ryan Sleevi 2015/03/19 04:38:25 no .get() ssl_info->client_cert_sent = client_cer
337 PRUint16 cipher_suite =
338 SSLConnectionStatusToCipherSuite(ssl_info->connection_status);
339 SSLCipherSuiteInfo cipher_info;
340 SECStatus ok =
341 SSL_GetCipherSuiteInfo(cipher_suite, &cipher_info, sizeof(cipher_info));
342 if (ok == SECSuccess) {
343 ssl_info->security_bits = cipher_info.effectiveKeyBits;
344 } else {
345 ssl_info->security_bits = -1;
346 }
347 PRBool last_handshake_resumed;
348 SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
349 if (rv == SECSuccess && last_handshake_resumed) {
350 ssl_info->handshake_type = SSLInfo::HANDSHAKE_RESUME;
351 } else {
352 ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL;
353 }
354 return true;
Ryan Sleevi 2015/03/19 04:38:25 Feels pretty unreadable/ wall of text. Break it in
308 } 355 }
309 356
310 int SSLServerSocketNSS::InitializeSSLOptions() { 357 int SSLServerSocketNSS::InitializeSSLOptions() {
311 // Transport connected, now hook it up to nss 358 // Transport connected, now hook it up to nss
312 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize); 359 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
313 if (nss_fd_ == NULL) { 360 if (nss_fd_ == NULL) {
314 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. 361 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
315 } 362 }
316 363
317 // Grab pointer to buffers 364 // Grab pointer to buffers
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT"); 434 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
388 return ERR_UNEXPECTED; 435 return ERR_UNEXPECTED;
389 } 436 }
390 437
391 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE); 438 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
392 if (rv != SECSuccess) { 439 if (rv != SECSuccess) {
393 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER"); 440 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
394 return ERR_UNEXPECTED; 441 return ERR_UNEXPECTED;
395 } 442 }
396 443
397 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE); 444 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE,
445 ssl_config_.send_client_cert ? PR_TRUE : PR_FALSE);
398 if (rv != SECSuccess) { 446 if (rv != SECSuccess) {
399 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE"); 447 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
400 return ERR_UNEXPECTED; 448 return ERR_UNEXPECTED;
401 } 449 }
402 450
403 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE); 451 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE,
452 client_cert_verifier_ ? PR_TRUE : PR_FALSE);
404 if (rv != SECSuccess) { 453 if (rv != SECSuccess) {
405 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE"); 454 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
406 return ERR_UNEXPECTED; 455 return ERR_UNEXPECTED;
407 } 456 }
408 457
409 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this); 458 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
410 if (rv != SECSuccess) { 459 if (rv != SECSuccess) {
411 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", ""); 460 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
412 return ERR_UNEXPECTED; 461 return ERR_UNEXPECTED;
413 } 462 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 return ERR_UNEXPECTED; 532 return ERR_UNEXPECTED;
484 } 533 }
485 534
486 // Tell SSL we're a server; needed if not letting NSPR do socket I/O 535 // Tell SSL we're a server; needed if not letting NSPR do socket I/O
487 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE); 536 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
488 if (rv != SECSuccess) { 537 if (rv != SECSuccess) {
489 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", ""); 538 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
490 return ERR_UNEXPECTED; 539 return ERR_UNEXPECTED;
491 } 540 }
492 541
542 // Set up the information needed for the CertificateRequest message
543 if (!client_cert_ca_list_.empty()) {
544 CERTCertList* certs = CERT_NewCertList();
545 if (!certs) {
546 LogFailedNSSFunction(net_log_, "CERT_NewCertList", "");
547 return ERR_UNEXPECTED;
548 }
549 for (CertificateList::const_iterator it = client_cert_ca_list_.begin();
550 it != client_cert_ca_list_.end(); ++it) {
Ryan Sleevi 2015/03/19 04:38:25 for (const auto& certificate : client_cert_ca_list
551 CERT_AddCertToListTail(certs,
552 CERT_DupCertificate((*it)->os_cert_handle()));
553 }
554
555 rv = SSL_SetTrustAnchors(nss_fd_, certs);
556 CERT_DestroyCertList(certs);
557 if (rv != SECSuccess) {
558 LogFailedNSSFunction(net_log_, "SSL_SetTrustAnchors", "");
559 return ERR_UNEXPECTED;
560 }
561 }
562
493 return OK; 563 return OK;
494 } 564 }
495 565
496 void SSLServerSocketNSS::OnSendComplete(int result) { 566 void SSLServerSocketNSS::OnSendComplete(int result) {
497 if (next_handshake_state_ == STATE_HANDSHAKE) { 567 if (next_handshake_state_ == STATE_HANDSHAKE) {
498 // In handshake phase. 568 // In handshake phase.
499 OnHandshakeIOComplete(result); 569 OnHandshakeIOComplete(result);
500 return; 570 return;
501 } 571 }
502 572
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 DCHECK(rv != ERR_IO_PENDING); 867 DCHECK(rv != ERR_IO_PENDING);
798 DCHECK(!user_write_callback_.is_null()); 868 DCHECK(!user_write_callback_.is_null());
799 869
800 user_write_buf_ = NULL; 870 user_write_buf_ = NULL;
801 user_write_buf_len_ = 0; 871 user_write_buf_len_ = 0;
802 ResetAndReturn(&user_write_callback_).Run(rv); 872 ResetAndReturn(&user_write_callback_).Run(rv);
803 } 873 }
804 874
805 // static 875 // static
806 // NSS calls this if an incoming certificate needs to be verified. 876 // NSS calls this if an incoming certificate needs to be verified.
807 // Do nothing but return SECSuccess.
808 // This is called only in full handshake mode. 877 // This is called only in full handshake mode.
809 // Peer certificate is retrieved in HandshakeCallback() later, which is called 878 // Peer certificate is retrieved in HandshakeCallback() later, which is called
810 // in full handshake mode or in resumption handshake mode. 879 // in full handshake mode or in resumption handshake mode.
811 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg, 880 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
812 PRFileDesc* socket, 881 PRFileDesc* socket,
813 PRBool checksig, 882 PRBool checksig,
814 PRBool is_server) { 883 PRBool is_server) {
815 // TODO(hclam): Implement. 884 if (!is_server)
816 // Tell NSS to not verify the certificate. 885 return SECFailure;
817 return SECSuccess; 886 SSLServerSocketNSS* self = reinterpret_cast<SSLServerSocketNSS*>(arg);
887 DCHECK(self);
888 if (!self->client_cert_verifier_)
889 return SECSuccess;
890 self->ExtractClientCert();
891 X509Certificate* cert = self->client_cert_.get();
892 if (!cert) {
893 PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0);
894 return SECFailure;
895 }
896 CertVerifyResult ignore_result;
897 CertVerifier::RequestHandle ignore_handle;
898 int res = self->client_cert_verifier_->Verify(
899 cert, std::string(), 0, NULL, &ignore_result,
900 base::Bind(&DoNothingOnCompletion), &ignore_handle, self->net_log_);
901 if (res != OK) {
902 PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
903 }
Ryan Sleevi 2015/03/19 04:38:25 no braces
904 return res == OK ? SECSuccess : SECFailure;
818 } 905 }
819 906
820 // static 907 // static
821 // NSS calls this when handshake is completed. 908 // NSS calls this when handshake is completed.
822 // After the SSL handshake is finished we need to verify the certificate. 909 // After the SSL handshake is finished we need to verify the certificate.
823 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, 910 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
824 void* arg) { 911 void* arg) {
825 // TODO(hclam): Implement. 912 // TODO(hclam): Implement.
826 } 913 }
827 914
828 int SSLServerSocketNSS::Init() { 915 int SSLServerSocketNSS::Init() {
829 // Initialize the NSS SSL library in a threadsafe way. This also 916 // Initialize the NSS SSL library in a threadsafe way. This also
830 // initializes the NSS base library. 917 // initializes the NSS base library.
831 EnsureNSSSSLInit(); 918 EnsureNSSSSLInit();
832 if (!NSS_IsInitialized()) 919 if (!NSS_IsInitialized())
833 return ERR_UNEXPECTED; 920 return ERR_UNEXPECTED;
834 921
835 EnableSSLServerSockets(); 922 EnableSSLServerSockets();
836 return OK; 923 return OK;
837 } 924 }
838 925
926 void SSLServerSocketNSS::ExtractClientCert() {
927 if (client_cert_.get())
928 return;
929 if (!completed_handshake_)
930 return;
931 CERTCertList* list = SSL_PeerCertificateChain(nss_fd_);
Ryan Sleevi 2015/03/19 04:38:25 Use a scoped type helper
932 if (list == NULL)
933 return;
934 std::vector<base::StringPiece> certs;
935 for (CERTCertListNode* node = CERT_LIST_HEAD(list);
936 !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) {
937 SECItem& cert_der = node->cert->derCert;
938 base::StringPiece cert(reinterpret_cast<char*>(cert_der.data),
939 cert_der.len);
940 certs.push_back(cert);
941 }
942 client_cert_ = X509Certificate::CreateFromDERCertChain(certs);
943 CERT_DestroyCertList(list);
944 }
945
839 } // namespace net 946 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698