Chromium Code Reviews| 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 |