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_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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |