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

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: 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_nss.h ('k') | net/socket/ssl_server_socket_openssl.h » ('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_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/logging.h" 34 #include "base/logging.h"
35 #include "base/memory/ref_counted.h" 35 #include "base/memory/ref_counted.h"
36 #include "crypto/nss_util_internal.h" 36 #include "crypto/nss_util_internal.h"
37 #include "crypto/rsa_private_key.h" 37 #include "crypto/rsa_private_key.h"
38 #include "net/base/io_buffer.h" 38 #include "net/base/io_buffer.h"
39 #include "net/base/net_errors.h" 39 #include "net/base/net_errors.h"
40 #include "net/cert/cert_verifier.h"
41 #include "net/cert/cert_verify_result.h"
40 #include "net/log/net_log.h" 42 #include "net/log/net_log.h"
41 #include "net/socket/nss_ssl_util.h" 43 #include "net/socket/nss_ssl_util.h"
44 #include "net/ssl/ssl_connection_status_flags.h"
45 #include "net/ssl/ssl_info.h"
42 46
43 // SSL plaintext fragments are shorter than 16KB. Although the record layer 47 // SSL plaintext fragments are shorter than 16KB. Although the record layer
44 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much 48 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
45 // smaller than 1KB. So a 17KB buffer should be large enough to hold an 49 // smaller than 1KB. So a 17KB buffer should be large enough to hold an
46 // entire SSL record. 50 // entire SSL record.
47 static const int kRecvBufferSize = 17 * 1024; 51 static const int kRecvBufferSize = 17 * 1024;
48 static const int kSendBufferSize = 17 * 1024; 52 static const int kSendBufferSize = 17 * 1024;
49 53
50 #define GotoState(s) next_handshake_state_ = s 54 #define GotoState(s) next_handshake_state_ = s
51 55
(...skipping 11 matching lines...) Expand all
63 SSL_ConfigServerSessionIDCache(64, 28800, 28800, NULL); 67 SSL_ConfigServerSessionIDCache(64, 28800, 28800, NULL);
64 g_nss_server_sockets_init = true; 68 g_nss_server_sockets_init = true;
65 } 69 }
66 70
67 ~NSSSSLServerInitSingleton() { 71 ~NSSSSLServerInitSingleton() {
68 SSL_ShutdownServerSessionIDCache(); 72 SSL_ShutdownServerSessionIDCache();
69 g_nss_server_sockets_init = false; 73 g_nss_server_sockets_init = false;
70 } 74 }
71 }; 75 };
72 76
77 void DoNothingOnCompletion(int ignore) {}
78
73 static base::LazyInstance<NSSSSLServerInitSingleton>::Leaky 79 static base::LazyInstance<NSSSSLServerInitSingleton>::Leaky
74 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER; 80 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
75 81
76 } // namespace 82 } // namespace
77 83
78 void EnableSSLServerSockets() { 84 void EnableSSLServerSockets() {
79 g_nss_ssl_server_init_singleton.Get(); 85 g_nss_ssl_server_init_singleton.Get();
80 } 86 }
81 87
82 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( 88 scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
83 scoped_ptr<StreamSocket> socket, 89 scoped_ptr<StreamSocket> socket,
84 X509Certificate* cert, 90 X509Certificate* certificate,
85 crypto::RSAPrivateKey* key, 91 crypto::RSAPrivateKey* key,
86 const SSLServerConfig& ssl_config) { 92 const SSLServerConfig& ssl_config) {
87 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been" 93 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
88 << " called yet!"; 94 << " called yet!";
89 95
90 return scoped_ptr<SSLServerSocket>( 96 return scoped_ptr<SSLServerSocket>(
91 new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config)); 97 new SSLServerSocketNSS(socket.Pass(), certificate, key, ssl_config));
92 } 98 }
93 99
94 SSLServerSocketNSS::SSLServerSocketNSS( 100 SSLServerSocketNSS::SSLServerSocketNSS(
95 scoped_ptr<StreamSocket> transport_socket, 101 scoped_ptr<StreamSocket> transport_socket,
96 scoped_refptr<X509Certificate> cert, 102 scoped_refptr<X509Certificate> cert,
97 crypto::RSAPrivateKey* key, 103 crypto::RSAPrivateKey* key,
98 const SSLServerConfig& ssl_config) 104 const SSLServerConfig& ssl_config)
99 : transport_send_busy_(false), 105 : transport_send_busy_(false),
100 transport_recv_busy_(false), 106 transport_recv_busy_(false),
101 user_read_buf_len_(0), 107 user_read_buf_len_(0),
102 user_write_buf_len_(0), 108 user_write_buf_len_(0),
103 nss_fd_(NULL), 109 nss_fd_(NULL),
104 nss_bufs_(NULL), 110 nss_bufs_(NULL),
105 transport_socket_(transport_socket.Pass()), 111 transport_socket_(transport_socket.Pass()),
106 ssl_config_(ssl_config), 112 ssl_config_(ssl_config),
107 cert_(cert), 113 cert_(cert),
108 next_handshake_state_(STATE_NONE), 114 next_handshake_state_(STATE_NONE),
109 completed_handshake_(false) { 115 completed_handshake_(false),
116 client_cert_ca_list_(),
117 client_cert_verifier_(NULL) {
110 // TODO(hclam): Need a better way to clone a key. 118 // TODO(hclam): Need a better way to clone a key.
111 std::vector<uint8> key_bytes; 119 std::vector<uint8> key_bytes;
112 CHECK(key->ExportPrivateKey(&key_bytes)); 120 CHECK(key->ExportPrivateKey(&key_bytes));
113 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); 121 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
114 CHECK(key_.get()); 122 CHECK(key_.get());
115 } 123 }
116 124
117 SSLServerSocketNSS::~SSLServerSocketNSS() { 125 SSLServerSocketNSS::~SSLServerSocketNSS() {
118 if (nss_fd_ != NULL) { 126 if (nss_fd_ != NULL) {
119 PR_Close(nss_fd_); 127 PR_Close(nss_fd_);
(...skipping 28 matching lines...) Expand all
148 rv = DoHandshakeLoop(OK); 156 rv = DoHandshakeLoop(OK);
149 if (rv == ERR_IO_PENDING) { 157 if (rv == ERR_IO_PENDING) {
150 user_handshake_callback_ = callback; 158 user_handshake_callback_ = callback;
151 } else { 159 } else {
152 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv); 160 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
153 } 161 }
154 162
155 return rv > OK ? OK : rv; 163 return rv > OK ? OK : rv;
156 } 164 }
157 165
166 void SSLServerSocketNSS::SetRequireClientCert(bool require_client_cert) {
167 ssl_config_.require_client_cert = require_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
158 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label, 180 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
159 bool has_context, 181 bool has_context,
160 const base::StringPiece& context, 182 const base::StringPiece& context,
161 unsigned char* out, 183 unsigned char* out,
162 unsigned int outlen) { 184 unsigned int outlen) {
163 if (!IsConnected()) 185 if (!IsConnected())
164 return ERR_SOCKET_NOT_CONNECTED; 186 return ERR_SOCKET_NOT_CONNECTED;
165 SECStatus result = SSL_ExportKeyingMaterial( 187 SECStatus result = SSL_ExportKeyingMaterial(
166 nss_fd_, label.data(), label.size(), has_context, 188 nss_fd_, label.data(), label.size(), has_context,
167 reinterpret_cast<const unsigned char*>(context.data()), 189 reinterpret_cast<const unsigned char*>(context.data()),
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 NOTIMPLEMENTED(); 319 NOTIMPLEMENTED();
298 return false; 320 return false;
299 } 321 }
300 322
301 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const { 323 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
302 // NPN is not supported by this class. 324 // NPN is not supported by this class.
303 return kProtoUnknown; 325 return kProtoUnknown;
304 } 326 }
305 327
306 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { 328 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
307 NOTIMPLEMENTED(); 329 ssl_info->Reset();
308 return false; 330 if (!completed_handshake_) {
331 return false;
332 }
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;
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;
309 } 355 }
310 356
311 void SSLServerSocketNSS::GetConnectionAttempts(ConnectionAttempts* out) const { 357 void SSLServerSocketNSS::GetConnectionAttempts(ConnectionAttempts* out) const {
312 out->clear(); 358 out->clear();
313 } 359 }
314 360
315 int64_t SSLServerSocketNSS::GetTotalReceivedBytes() const { 361 int64_t SSLServerSocketNSS::GetTotalReceivedBytes() const {
316 NOTIMPLEMENTED(); 362 NOTIMPLEMENTED();
317 return 0; 363 return 0;
318 } 364 }
(...skipping 12 matching lines...) Expand all
331 /* Push SSL onto our fake I/O socket */ 377 /* Push SSL onto our fake I/O socket */
332 nss_fd_ = SSL_ImportFD(NULL, nss_fd_); 378 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
333 if (nss_fd_ == NULL) { 379 if (nss_fd_ == NULL) {
334 LogFailedNSSFunction(net_log_, "SSL_ImportFD", ""); 380 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
335 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code. 381 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
336 } 382 }
337 // TODO(port): set more ssl options! Check errors! 383 // TODO(port): set more ssl options! Check errors!
338 384
339 int rv; 385 int rv;
340 386
341 if (ssl_config_.require_client_cert) {
342 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
343 if (rv != SECSuccess) {
344 LogFailedNSSFunction(net_log_, "SSL_OptionSet",
345 "SSL_REQUEST_CERTIFICATE");
346 return ERR_UNEXPECTED;
347 }
348 }
349
350 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE); 387 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
351 if (rv != SECSuccess) { 388 if (rv != SECSuccess) {
352 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY"); 389 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
353 return ERR_UNEXPECTED; 390 return ERR_UNEXPECTED;
354 } 391 }
355 392
356 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE); 393 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
357 if (rv != SECSuccess) { 394 if (rv != SECSuccess) {
358 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2"); 395 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
359 return ERR_UNEXPECTED; 396 return ERR_UNEXPECTED;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT"); 442 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
406 return ERR_UNEXPECTED; 443 return ERR_UNEXPECTED;
407 } 444 }
408 445
409 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE); 446 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
410 if (rv != SECSuccess) { 447 if (rv != SECSuccess) {
411 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER"); 448 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
412 return ERR_UNEXPECTED; 449 return ERR_UNEXPECTED;
413 } 450 }
414 451
415 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE); 452 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE,
453 ssl_config_.require_client_cert ? PR_TRUE : PR_FALSE);
416 if (rv != SECSuccess) { 454 if (rv != SECSuccess) {
417 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE"); 455 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
418 return ERR_UNEXPECTED; 456 return ERR_UNEXPECTED;
419 } 457 }
420 458
421 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE); 459 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE,
460 ssl_config_.require_client_cert ? PR_TRUE : PR_FALSE);
422 if (rv != SECSuccess) { 461 if (rv != SECSuccess) {
423 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE"); 462 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
424 return ERR_UNEXPECTED; 463 return ERR_UNEXPECTED;
425 } 464 }
426 465
427 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this); 466 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
428 if (rv != SECSuccess) { 467 if (rv != SECSuccess) {
429 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", ""); 468 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
430 return ERR_UNEXPECTED; 469 return ERR_UNEXPECTED;
431 } 470 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 return ERR_UNEXPECTED; 540 return ERR_UNEXPECTED;
502 } 541 }
503 542
504 // Tell SSL we're a server; needed if not letting NSPR do socket I/O 543 // Tell SSL we're a server; needed if not letting NSPR do socket I/O
505 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE); 544 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
506 if (rv != SECSuccess) { 545 if (rv != SECSuccess) {
507 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", ""); 546 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
508 return ERR_UNEXPECTED; 547 return ERR_UNEXPECTED;
509 } 548 }
510 549
550 // Set up the information needed for the CertificateRequest message
551 if (!client_cert_ca_list_.empty()) {
552 CERTCertList* certs = CERT_NewCertList();
553 if (!certs) {
554 LogFailedNSSFunction(net_log_, "CERT_NewCertList", "");
555 return ERR_UNEXPECTED;
556 }
557 for (CertificateList::const_iterator it = client_cert_ca_list_.begin();
558 it != client_cert_ca_list_.end(); ++it) {
559 CERT_AddCertToListTail(certs,
560 CERT_DupCertificate((*it)->os_cert_handle()));
561 }
562
563 rv = SSL_SetTrustAnchors(nss_fd_, certs);
564 CERT_DestroyCertList(certs);
565 if (rv != SECSuccess) {
566 LogFailedNSSFunction(net_log_, "SSL_SetTrustAnchors", "");
567 return ERR_UNEXPECTED;
568 }
569 }
570
511 return OK; 571 return OK;
512 } 572 }
513 573
514 void SSLServerSocketNSS::OnSendComplete(int result) { 574 void SSLServerSocketNSS::OnSendComplete(int result) {
515 if (next_handshake_state_ == STATE_HANDSHAKE) { 575 if (next_handshake_state_ == STATE_HANDSHAKE) {
516 // In handshake phase. 576 // In handshake phase.
517 OnHandshakeIOComplete(result); 577 OnHandshakeIOComplete(result);
518 return; 578 return;
519 } 579 }
520 580
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 DCHECK(rv != ERR_IO_PENDING); 875 DCHECK(rv != ERR_IO_PENDING);
816 DCHECK(!user_write_callback_.is_null()); 876 DCHECK(!user_write_callback_.is_null());
817 877
818 user_write_buf_ = NULL; 878 user_write_buf_ = NULL;
819 user_write_buf_len_ = 0; 879 user_write_buf_len_ = 0;
820 ResetAndReturn(&user_write_callback_).Run(rv); 880 ResetAndReturn(&user_write_callback_).Run(rv);
821 } 881 }
822 882
823 // static 883 // static
824 // NSS calls this if an incoming certificate needs to be verified. 884 // NSS calls this if an incoming certificate needs to be verified.
825 // Do nothing but return SECSuccess.
826 // This is called only in full handshake mode. 885 // This is called only in full handshake mode.
827 // Peer certificate is retrieved in HandshakeCallback() later, which is called 886 // Peer certificate is retrieved in HandshakeCallback() later, which is called
828 // in full handshake mode or in resumption handshake mode. 887 // in full handshake mode or in resumption handshake mode.
829 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg, 888 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
830 PRFileDesc* socket, 889 PRFileDesc* socket,
831 PRBool checksig, 890 PRBool checksig,
832 PRBool is_server) { 891 PRBool is_server) {
833 // TODO(hclam): Implement. 892 if (!is_server)
834 // Tell NSS to not verify the certificate. 893 return SECFailure;
835 return SECSuccess; 894 SSLServerSocketNSS* self = reinterpret_cast<SSLServerSocketNSS*>(arg);
895 DCHECK(self);
896 if (!self->client_cert_verifier_)
897 return SECSuccess;
898 self->ExtractClientCert();
899 X509Certificate* cert = self->client_cert_.get();
900 if (!cert) {
901 PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0);
902 return SECFailure;
903 }
904 CertVerifyResult ignore_result;
905 scoped_ptr<CertVerifier::Request> ignore_async;
906 int res = self->client_cert_verifier_->Verify(
907 cert, std::string(), std::string(), 0, NULL, &ignore_result,
908 base::Bind(&DoNothingOnCompletion), &ignore_async, self->net_log_);
909 if (res != OK) {
910 PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
911 }
912 return res == OK ? SECSuccess : SECFailure;
836 } 913 }
837 914
838 // static 915 // static
839 // NSS calls this when handshake is completed. 916 // NSS calls this when handshake is completed.
840 // After the SSL handshake is finished we need to verify the certificate. 917 // After the SSL handshake is finished we need to verify the certificate.
841 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, 918 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
842 void* arg) { 919 void* arg) {
843 // TODO(hclam): Implement. 920 // TODO(hclam): Implement.
844 } 921 }
845 922
846 int SSLServerSocketNSS::Init() { 923 int SSLServerSocketNSS::Init() {
847 // Initialize the NSS SSL library in a threadsafe way. This also 924 // Initialize the NSS SSL library in a threadsafe way. This also
848 // initializes the NSS base library. 925 // initializes the NSS base library.
849 EnsureNSSSSLInit(); 926 EnsureNSSSSLInit();
850 if (!NSS_IsInitialized()) 927 if (!NSS_IsInitialized())
851 return ERR_UNEXPECTED; 928 return ERR_UNEXPECTED;
852 929
853 EnableSSLServerSockets(); 930 EnableSSLServerSockets();
854 return OK; 931 return OK;
855 } 932 }
856 933
934 void SSLServerSocketNSS::ExtractClientCert() {
935 if (client_cert_.get())
936 return;
937 if (!completed_handshake_)
938 return;
939 CERTCertList* list = SSL_PeerCertificateChain(nss_fd_);
940 if (list == NULL)
941 return;
942 std::vector<base::StringPiece> certs;
943 for (CERTCertListNode* node = CERT_LIST_HEAD(list);
944 !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) {
945 SECItem& cert_der = node->cert->derCert;
946 base::StringPiece cert(reinterpret_cast<char*>(cert_der.data),
947 cert_der.len);
948 certs.push_back(cert);
949 }
950 client_cert_ = X509Certificate::CreateFromDERCertChain(certs);
951 CERT_DestroyCertList(list);
952 }
953
857 } // namespace net 954 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_server_socket_nss.h ('k') | net/socket/ssl_server_socket_openssl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698