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

Side by Side Diff: net/socket/ssl_server_socket_nss.cc

Issue 1882433002: Removing NSS files and USE_OPENSSL flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 8 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
« no previous file with comments | « net/socket/ssl_server_socket_nss.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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/socket/ssl_server_socket_nss.h"
6
7 #include <utility>
8
9 #if defined(OS_WIN)
10 #include <winsock2.h>
11 #endif
12
13 #if defined(USE_SYSTEM_SSL)
14 #include <dlfcn.h>
15 #endif
16 #if defined(OS_MACOSX)
17 #include <Security/Security.h>
18 #endif
19 #include <certdb.h>
20 #include <cryptohi.h>
21 #include <hasht.h>
22 #include <keyhi.h>
23 #include <nspr.h>
24 #include <nss.h>
25 #include <pk11pub.h>
26 #include <secerr.h>
27 #include <sechash.h>
28 #include <ssl.h>
29 #include <sslerr.h>
30 #include <sslproto.h>
31
32 #include <limits>
33
34 #include "base/callback_helpers.h"
35 #include "base/lazy_instance.h"
36 #include "base/logging.h"
37 #include "base/memory/ref_counted.h"
38 #include "crypto/nss_util_internal.h"
39 #include "crypto/rsa_private_key.h"
40 #include "net/base/io_buffer.h"
41 #include "net/base/net_errors.h"
42 #include "net/log/net_log.h"
43 #include "net/socket/nss_ssl_util.h"
44
45 // SSL plaintext fragments are shorter than 16KB. Although the record layer
46 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
47 // smaller than 1KB. So a 17KB buffer should be large enough to hold an
48 // entire SSL record.
49 static const int kRecvBufferSize = 17 * 1024;
50 static const int kSendBufferSize = 17 * 1024;
51
52 #define GotoState(s) next_handshake_state_ = s
53
54 namespace net {
55
56 namespace {
57
58 bool g_nss_server_sockets_init = false;
59
60 class NSSSSLServerInitSingleton {
61 public:
62 NSSSSLServerInitSingleton() {
63 EnsureNSSSSLInit();
64
65 SSL_ConfigServerSessionIDCache(64, 28800, 28800, NULL);
66 g_nss_server_sockets_init = true;
67 }
68
69 ~NSSSSLServerInitSingleton() {
70 SSL_ShutdownServerSessionIDCache();
71 g_nss_server_sockets_init = false;
72 }
73 };
74
75 static base::LazyInstance<NSSSSLServerInitSingleton>::Leaky
76 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
77
78 class SSLServerSocketNSS : public SSLServerSocket {
79 public:
80 // See comments on CreateSSLServerSocket for details of how these
81 // parameters are used.
82 SSLServerSocketNSS(std::unique_ptr<StreamSocket> socket,
83 X509Certificate* certificate,
84 const crypto::RSAPrivateKey& key,
85 const SSLServerConfig& ssl_server_config);
86 ~SSLServerSocketNSS() override;
87
88 // SSLServerSocket interface.
89 int Handshake(const CompletionCallback& callback) override;
90
91 // SSLSocket interface.
92 int ExportKeyingMaterial(const base::StringPiece& label,
93 bool has_context,
94 const base::StringPiece& context,
95 unsigned char* out,
96 unsigned int outlen) override;
97
98 // Socket interface (via StreamSocket).
99 int Read(IOBuffer* buf,
100 int buf_len,
101 const CompletionCallback& callback) override;
102 int Write(IOBuffer* buf,
103 int buf_len,
104 const CompletionCallback& callback) override;
105 int SetReceiveBufferSize(int32_t size) override;
106 int SetSendBufferSize(int32_t size) override;
107
108 // StreamSocket implementation.
109 int Connect(const CompletionCallback& callback) override;
110 void Disconnect() override;
111 bool IsConnected() const override;
112 bool IsConnectedAndIdle() const override;
113 int GetPeerAddress(IPEndPoint* address) const override;
114 int GetLocalAddress(IPEndPoint* address) const override;
115 const BoundNetLog& NetLog() const override;
116 void SetSubresourceSpeculation() override;
117 void SetOmniboxSpeculation() override;
118 bool WasEverUsed() const override;
119 bool WasNpnNegotiated() const override;
120 NextProto GetNegotiatedProtocol() const override;
121 bool GetSSLInfo(SSLInfo* ssl_info) override;
122 void GetConnectionAttempts(ConnectionAttempts* out) const override;
123 void ClearConnectionAttempts() override {}
124 void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
125 int64_t GetTotalReceivedBytes() const override;
126
127 private:
128 enum State {
129 STATE_NONE,
130 STATE_HANDSHAKE,
131 };
132
133 int InitializeSSLOptions();
134
135 void OnSendComplete(int result);
136 void OnRecvComplete(int result);
137 void OnHandshakeIOComplete(int result);
138
139 int BufferSend();
140 void BufferSendComplete(int result);
141 int BufferRecv();
142 void BufferRecvComplete(int result);
143 bool DoTransportIO();
144 int DoPayloadRead();
145 int DoPayloadWrite();
146
147 int DoHandshakeLoop(int last_io_result);
148 int DoReadLoop(int result);
149 int DoWriteLoop(int result);
150 int DoHandshake();
151 void DoHandshakeCallback(int result);
152 void DoReadCallback(int result);
153 void DoWriteCallback(int result);
154
155 static SECStatus OwnAuthCertHandler(void* arg,
156 PRFileDesc* socket,
157 PRBool checksig,
158 PRBool is_server);
159 static void HandshakeCallback(PRFileDesc* socket, void* arg);
160
161 int Init();
162
163 // Members used to send and receive buffer.
164 bool transport_send_busy_;
165 bool transport_recv_busy_;
166
167 scoped_refptr<IOBuffer> recv_buffer_;
168
169 BoundNetLog net_log_;
170
171 CompletionCallback user_handshake_callback_;
172 CompletionCallback user_read_callback_;
173 CompletionCallback user_write_callback_;
174
175 // Used by Read function.
176 scoped_refptr<IOBuffer> user_read_buf_;
177 int user_read_buf_len_;
178
179 // Used by Write function.
180 scoped_refptr<IOBuffer> user_write_buf_;
181 int user_write_buf_len_;
182
183 // The NSS SSL state machine
184 PRFileDesc* nss_fd_;
185
186 // Buffers for the network end of the SSL state machine
187 memio_Private* nss_bufs_;
188
189 // StreamSocket for sending and receiving data.
190 std::unique_ptr<StreamSocket> transport_socket_;
191
192 // Options for the SSL socket.
193 SSLServerConfig ssl_server_config_;
194
195 // Certificate for the server.
196 scoped_refptr<X509Certificate> cert_;
197
198 // Private key used by the server.
199 std::unique_ptr<crypto::RSAPrivateKey> key_;
200
201 State next_handshake_state_;
202 bool completed_handshake_;
203
204 DISALLOW_COPY_AND_ASSIGN(SSLServerSocketNSS);
205 };
206
207 SSLServerSocketNSS::SSLServerSocketNSS(
208 std::unique_ptr<StreamSocket> transport_socket,
209 X509Certificate* cert,
210 const crypto::RSAPrivateKey& key,
211 const SSLServerConfig& ssl_server_config)
212 : transport_send_busy_(false),
213 transport_recv_busy_(false),
214 user_read_buf_len_(0),
215 user_write_buf_len_(0),
216 nss_fd_(NULL),
217 nss_bufs_(NULL),
218 transport_socket_(std::move(transport_socket)),
219 ssl_server_config_(ssl_server_config),
220 cert_(cert),
221 key_(key.Copy()),
222 next_handshake_state_(STATE_NONE),
223 completed_handshake_(false) {
224 CHECK(key_);
225 }
226
227 SSLServerSocketNSS::~SSLServerSocketNSS() {
228 if (nss_fd_ != NULL) {
229 PR_Close(nss_fd_);
230 nss_fd_ = NULL;
231 }
232 }
233
234 int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
235 net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
236
237 int rv = Init();
238 if (rv != OK) {
239 LOG(ERROR) << "Failed to initialize NSS";
240 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
241 return rv;
242 }
243
244 rv = InitializeSSLOptions();
245 if (rv != OK) {
246 LOG(ERROR) << "Failed to initialize SSL options";
247 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
248 return rv;
249 }
250
251 // Set peer address. TODO(hclam): This should be in a separate method.
252 PRNetAddr peername;
253 memset(&peername, 0, sizeof(peername));
254 peername.raw.family = AF_INET;
255 memio_SetPeerName(nss_fd_, &peername);
256
257 GotoState(STATE_HANDSHAKE);
258 rv = DoHandshakeLoop(OK);
259 if (rv == ERR_IO_PENDING) {
260 user_handshake_callback_ = callback;
261 } else {
262 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
263 }
264
265 return rv > OK ? OK : rv;
266 }
267
268 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
269 bool has_context,
270 const base::StringPiece& context,
271 unsigned char* out,
272 unsigned int outlen) {
273 if (!IsConnected())
274 return ERR_SOCKET_NOT_CONNECTED;
275 SECStatus result = SSL_ExportKeyingMaterial(
276 nss_fd_, label.data(), label.size(), has_context,
277 reinterpret_cast<const unsigned char*>(context.data()),
278 context.length(), out, outlen);
279 if (result != SECSuccess) {
280 LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
281 return MapNSSError(PORT_GetError());
282 }
283 return OK;
284 }
285
286 int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
287 NOTIMPLEMENTED();
288 return ERR_NOT_IMPLEMENTED;
289 }
290
291 int SSLServerSocketNSS::Read(IOBuffer* buf,
292 int buf_len,
293 const CompletionCallback& callback) {
294 DCHECK(user_read_callback_.is_null());
295 DCHECK(user_handshake_callback_.is_null());
296 DCHECK(!user_read_buf_);
297 DCHECK(nss_bufs_);
298 DCHECK(!callback.is_null());
299
300 user_read_buf_ = buf;
301 user_read_buf_len_ = buf_len;
302
303 DCHECK(completed_handshake_);
304
305 int rv = DoReadLoop(OK);
306
307 if (rv == ERR_IO_PENDING) {
308 user_read_callback_ = callback;
309 } else {
310 user_read_buf_ = NULL;
311 user_read_buf_len_ = 0;
312 }
313 return rv;
314 }
315
316 int SSLServerSocketNSS::Write(IOBuffer* buf,
317 int buf_len,
318 const CompletionCallback& callback) {
319 DCHECK(user_write_callback_.is_null());
320 DCHECK(!user_write_buf_);
321 DCHECK(nss_bufs_);
322 DCHECK(!callback.is_null());
323
324 user_write_buf_ = buf;
325 user_write_buf_len_ = buf_len;
326
327 int rv = DoWriteLoop(OK);
328
329 if (rv == ERR_IO_PENDING) {
330 user_write_callback_ = callback;
331 } else {
332 user_write_buf_ = NULL;
333 user_write_buf_len_ = 0;
334 }
335 return rv;
336 }
337
338 int SSLServerSocketNSS::SetReceiveBufferSize(int32_t size) {
339 return transport_socket_->SetReceiveBufferSize(size);
340 }
341
342 int SSLServerSocketNSS::SetSendBufferSize(int32_t size) {
343 return transport_socket_->SetSendBufferSize(size);
344 }
345
346 bool SSLServerSocketNSS::IsConnected() const {
347 // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
348 // as well.
349 return completed_handshake_;
350 }
351
352 void SSLServerSocketNSS::Disconnect() {
353 transport_socket_->Disconnect();
354 }
355
356 bool SSLServerSocketNSS::IsConnectedAndIdle() const {
357 return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
358 }
359
360 int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
361 if (!IsConnected())
362 return ERR_SOCKET_NOT_CONNECTED;
363 return transport_socket_->GetPeerAddress(address);
364 }
365
366 int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
367 if (!IsConnected())
368 return ERR_SOCKET_NOT_CONNECTED;
369 return transport_socket_->GetLocalAddress(address);
370 }
371
372 const BoundNetLog& SSLServerSocketNSS::NetLog() const {
373 return net_log_;
374 }
375
376 void SSLServerSocketNSS::SetSubresourceSpeculation() {
377 transport_socket_->SetSubresourceSpeculation();
378 }
379
380 void SSLServerSocketNSS::SetOmniboxSpeculation() {
381 transport_socket_->SetOmniboxSpeculation();
382 }
383
384 bool SSLServerSocketNSS::WasEverUsed() const {
385 return transport_socket_->WasEverUsed();
386 }
387
388 bool SSLServerSocketNSS::WasNpnNegotiated() const {
389 NOTIMPLEMENTED();
390 return false;
391 }
392
393 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
394 // NPN is not supported by this class.
395 return kProtoUnknown;
396 }
397
398 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
399 NOTIMPLEMENTED();
400 return false;
401 }
402
403 void SSLServerSocketNSS::GetConnectionAttempts(ConnectionAttempts* out) const {
404 out->clear();
405 }
406
407 int64_t SSLServerSocketNSS::GetTotalReceivedBytes() const {
408 NOTIMPLEMENTED();
409 return 0;
410 }
411
412 int SSLServerSocketNSS::InitializeSSLOptions() {
413 // Transport connected, now hook it up to nss
414 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
415 if (nss_fd_ == NULL) {
416 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
417 }
418
419 // Grab pointer to buffers
420 nss_bufs_ = memio_GetSecret(nss_fd_);
421
422 /* Create SSL state machine */
423 /* Push SSL onto our fake I/O socket */
424 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
425 if (nss_fd_ == NULL) {
426 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
427 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
428 }
429 // TODO(port): set more ssl options! Check errors!
430
431 int rv;
432
433 if (ssl_server_config_.client_cert_type ==
434 SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT) {
435 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
436 if (rv != SECSuccess) {
437 LogFailedNSSFunction(net_log_, "SSL_OptionSet",
438 "SSL_REQUEST_CERTIFICATE");
439 return ERR_UNEXPECTED;
440 }
441 }
442
443 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
444 if (rv != SECSuccess) {
445 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
446 return ERR_UNEXPECTED;
447 }
448
449 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
450 if (rv != SECSuccess) {
451 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
452 return ERR_UNEXPECTED;
453 }
454
455 SSLVersionRange version_range;
456 version_range.min = ssl_server_config_.version_min;
457 version_range.max = ssl_server_config_.version_max;
458 rv = SSL_VersionRangeSet(nss_fd_, &version_range);
459 if (rv != SECSuccess) {
460 LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
461 return ERR_NO_SSL_VERSIONS_ENABLED;
462 }
463
464 if (ssl_server_config_.require_ecdhe) {
465 const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
466 const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
467
468 // Iterate over the cipher suites and disable those that don't use ECDHE.
469 for (unsigned i = 0; i < num_ciphers; i++) {
470 SSLCipherSuiteInfo info;
471 if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
472 SECSuccess) {
473 if (strcmp(info.keaTypeName, "ECDHE") != 0) {
474 SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
475 }
476 }
477 }
478 }
479
480 for (std::vector<uint16_t>::const_iterator it =
481 ssl_server_config_.disabled_cipher_suites.begin();
482 it != ssl_server_config_.disabled_cipher_suites.end(); ++it) {
483 // This will fail if the specified cipher is not implemented by NSS, but
484 // the failure is harmless.
485 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
486 }
487
488 // Server socket doesn't need session tickets.
489 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
490 if (rv != SECSuccess) {
491 LogFailedNSSFunction(
492 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
493 }
494
495 // Doing this will force PR_Accept perform handshake as server.
496 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
497 if (rv != SECSuccess) {
498 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
499 return ERR_UNEXPECTED;
500 }
501
502 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
503 if (rv != SECSuccess) {
504 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
505 return ERR_UNEXPECTED;
506 }
507
508 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
509 if (rv != SECSuccess) {
510 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
511 return ERR_UNEXPECTED;
512 }
513
514 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
515 if (rv != SECSuccess) {
516 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
517 return ERR_UNEXPECTED;
518 }
519
520 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
521 if (rv != SECSuccess) {
522 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
523 return ERR_UNEXPECTED;
524 }
525
526 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
527 if (rv != SECSuccess) {
528 LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
529 return ERR_UNEXPECTED;
530 }
531
532 // Get a certificate of CERTCertificate structure.
533 std::string der_string;
534 if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
535 return ERR_UNEXPECTED;
536
537 SECItem der_cert;
538 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
539 der_string.data()));
540 der_cert.len = der_string.length();
541 der_cert.type = siDERCertBuffer;
542
543 // Parse into a CERTCertificate structure.
544 CERTCertificate* cert = CERT_NewTempCertificate(
545 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
546 if (!cert) {
547 LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
548 return MapNSSError(PORT_GetError());
549 }
550
551 // Get a key of SECKEYPrivateKey* structure.
552 std::vector<uint8_t> key_vector;
553 if (!key_->ExportPrivateKey(&key_vector)) {
554 CERT_DestroyCertificate(cert);
555 return ERR_UNEXPECTED;
556 }
557
558 SECKEYPrivateKeyStr* private_key = NULL;
559 PK11SlotInfo* slot = PK11_GetInternalSlot();
560 if (!slot) {
561 CERT_DestroyCertificate(cert);
562 return ERR_UNEXPECTED;
563 }
564
565 SECItem der_private_key_info;
566 der_private_key_info.data =
567 const_cast<unsigned char*>(&key_vector.front());
568 der_private_key_info.len = key_vector.size();
569 // The server's RSA private key must be imported into NSS with the
570 // following key usage bits:
571 // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
572 // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
573 // exchange algorithms.
574 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
575 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
576 slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
577 key_usage, &private_key, NULL);
578 PK11_FreeSlot(slot);
579 if (rv != SECSuccess) {
580 CERT_DestroyCertificate(cert);
581 return ERR_UNEXPECTED;
582 }
583
584 // Assign server certificate and private key.
585 SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
586 rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
587 CERT_DestroyCertificate(cert);
588 SECKEY_DestroyPrivateKey(private_key);
589
590 if (rv != SECSuccess) {
591 PRErrorCode prerr = PR_GetError();
592 LOG(ERROR) << "Failed to config SSL server: " << prerr;
593 LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
594 return ERR_UNEXPECTED;
595 }
596
597 // Tell SSL we're a server; needed if not letting NSPR do socket I/O
598 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
599 if (rv != SECSuccess) {
600 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
601 return ERR_UNEXPECTED;
602 }
603
604 return OK;
605 }
606
607 void SSLServerSocketNSS::OnSendComplete(int result) {
608 if (next_handshake_state_ == STATE_HANDSHAKE) {
609 // In handshake phase.
610 OnHandshakeIOComplete(result);
611 return;
612 }
613
614 // TODO(byungchul): This state machine is not correct. Copy the state machine
615 // of SSLClientSocketNSS::OnSendComplete() which handles it better.
616 if (!completed_handshake_)
617 return;
618
619 if (user_write_buf_) {
620 int rv = DoWriteLoop(result);
621 if (rv != ERR_IO_PENDING)
622 DoWriteCallback(rv);
623 } else {
624 // Ensure that any queued ciphertext is flushed.
625 DoTransportIO();
626 }
627 }
628
629 void SSLServerSocketNSS::OnRecvComplete(int result) {
630 if (next_handshake_state_ == STATE_HANDSHAKE) {
631 // In handshake phase.
632 OnHandshakeIOComplete(result);
633 return;
634 }
635
636 // Network layer received some data, check if client requested to read
637 // decrypted data.
638 if (!user_read_buf_ || !completed_handshake_)
639 return;
640
641 int rv = DoReadLoop(result);
642 if (rv != ERR_IO_PENDING)
643 DoReadCallback(rv);
644 }
645
646 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
647 int rv = DoHandshakeLoop(result);
648 if (rv == ERR_IO_PENDING)
649 return;
650
651 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
652 if (!user_handshake_callback_.is_null())
653 DoHandshakeCallback(rv);
654 }
655
656 // Return 0 for EOF,
657 // > 0 for bytes transferred immediately,
658 // < 0 for error (or the non-error ERR_IO_PENDING).
659 int SSLServerSocketNSS::BufferSend(void) {
660 if (transport_send_busy_)
661 return ERR_IO_PENDING;
662
663 const char* buf1;
664 const char* buf2;
665 unsigned int len1, len2;
666 if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
667 // The error code itself is ignored, so just return ERR_ABORTED.
668 return ERR_ABORTED;
669 }
670 const size_t len = len1 + len2;
671
672 int rv = 0;
673 if (len) {
674 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
675 memcpy(send_buffer->data(), buf1, len1);
676 memcpy(send_buffer->data() + len1, buf2, len2);
677 rv = transport_socket_->Write(
678 send_buffer.get(), len,
679 base::Bind(&SSLServerSocketNSS::BufferSendComplete,
680 base::Unretained(this)));
681 if (rv == ERR_IO_PENDING) {
682 transport_send_busy_ = true;
683 } else {
684 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
685 }
686 }
687
688 return rv;
689 }
690
691 void SSLServerSocketNSS::BufferSendComplete(int result) {
692 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
693 transport_send_busy_ = false;
694 OnSendComplete(result);
695 }
696
697 int SSLServerSocketNSS::BufferRecv(void) {
698 if (transport_recv_busy_) return ERR_IO_PENDING;
699
700 char* buf;
701 int nb = memio_GetReadParams(nss_bufs_, &buf);
702 int rv;
703 if (!nb) {
704 // buffer too full to read into, so no I/O possible at moment
705 rv = ERR_IO_PENDING;
706 } else {
707 recv_buffer_ = new IOBuffer(nb);
708 rv = transport_socket_->Read(
709 recv_buffer_.get(), nb,
710 base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
711 base::Unretained(this)));
712 if (rv == ERR_IO_PENDING) {
713 transport_recv_busy_ = true;
714 } else {
715 if (rv > 0)
716 memcpy(buf, recv_buffer_->data(), rv);
717 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
718 recv_buffer_ = NULL;
719 }
720 }
721 return rv;
722 }
723
724 void SSLServerSocketNSS::BufferRecvComplete(int result) {
725 if (result > 0) {
726 char* buf;
727 memio_GetReadParams(nss_bufs_, &buf);
728 memcpy(buf, recv_buffer_->data(), result);
729 }
730 recv_buffer_ = NULL;
731 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
732 transport_recv_busy_ = false;
733 OnRecvComplete(result);
734 }
735
736 // Do as much network I/O as possible between the buffer and the
737 // transport socket. Return true if some I/O performed, false
738 // otherwise (error or ERR_IO_PENDING).
739 bool SSLServerSocketNSS::DoTransportIO() {
740 bool network_moved = false;
741 if (nss_bufs_ != NULL) {
742 int rv;
743 // Read and write as much data as we can. The loop is neccessary
744 // because Write() may return synchronously.
745 do {
746 rv = BufferSend();
747 if (rv > 0)
748 network_moved = true;
749 } while (rv > 0);
750 if (BufferRecv() >= 0)
751 network_moved = true;
752 }
753 return network_moved;
754 }
755
756 int SSLServerSocketNSS::DoPayloadRead() {
757 DCHECK(user_read_buf_);
758 DCHECK_GT(user_read_buf_len_, 0);
759 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
760 if (rv >= 0)
761 return rv;
762 PRErrorCode prerr = PR_GetError();
763 if (prerr == PR_WOULD_BLOCK_ERROR) {
764 return ERR_IO_PENDING;
765 }
766 rv = MapNSSError(prerr);
767 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
768 CreateNetLogSSLErrorCallback(rv, prerr));
769 return rv;
770 }
771
772 int SSLServerSocketNSS::DoPayloadWrite() {
773 DCHECK(user_write_buf_);
774 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
775 if (rv >= 0)
776 return rv;
777 PRErrorCode prerr = PR_GetError();
778 if (prerr == PR_WOULD_BLOCK_ERROR) {
779 return ERR_IO_PENDING;
780 }
781 rv = MapNSSError(prerr);
782 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
783 CreateNetLogSSLErrorCallback(rv, prerr));
784 return rv;
785 }
786
787 int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
788 int rv = last_io_result;
789 do {
790 // Default to STATE_NONE for next state.
791 // (This is a quirk carried over from the windows
792 // implementation. It makes reading the logs a bit harder.)
793 // State handlers can and often do call GotoState just
794 // to stay in the current state.
795 State state = next_handshake_state_;
796 GotoState(STATE_NONE);
797 switch (state) {
798 case STATE_HANDSHAKE:
799 rv = DoHandshake();
800 break;
801 case STATE_NONE:
802 default:
803 rv = ERR_UNEXPECTED;
804 LOG(DFATAL) << "unexpected state " << state;
805 break;
806 }
807
808 // Do the actual network I/O
809 bool network_moved = DoTransportIO();
810 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
811 // In general we exit the loop if rv is ERR_IO_PENDING. In this
812 // special case we keep looping even if rv is ERR_IO_PENDING because
813 // the transport IO may allow DoHandshake to make progress.
814 rv = OK; // This causes us to stay in the loop.
815 }
816 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
817 return rv;
818 }
819
820 int SSLServerSocketNSS::DoReadLoop(int result) {
821 DCHECK(completed_handshake_);
822 DCHECK(next_handshake_state_ == STATE_NONE);
823
824 if (result < 0)
825 return result;
826
827 if (!nss_bufs_) {
828 LOG(DFATAL) << "!nss_bufs_";
829 int rv = ERR_UNEXPECTED;
830 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
831 CreateNetLogSSLErrorCallback(rv, 0));
832 return rv;
833 }
834
835 bool network_moved;
836 int rv;
837 do {
838 rv = DoPayloadRead();
839 network_moved = DoTransportIO();
840 } while (rv == ERR_IO_PENDING && network_moved);
841 return rv;
842 }
843
844 int SSLServerSocketNSS::DoWriteLoop(int result) {
845 DCHECK(completed_handshake_);
846 DCHECK_EQ(next_handshake_state_, STATE_NONE);
847
848 if (result < 0)
849 return result;
850
851 if (!nss_bufs_) {
852 LOG(DFATAL) << "!nss_bufs_";
853 int rv = ERR_UNEXPECTED;
854 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
855 CreateNetLogSSLErrorCallback(rv, 0));
856 return rv;
857 }
858
859 bool network_moved;
860 int rv;
861 do {
862 rv = DoPayloadWrite();
863 network_moved = DoTransportIO();
864 } while (rv == ERR_IO_PENDING && network_moved);
865 return rv;
866 }
867
868 int SSLServerSocketNSS::DoHandshake() {
869 int net_error = OK;
870 SECStatus rv = SSL_ForceHandshake(nss_fd_);
871
872 if (rv == SECSuccess) {
873 completed_handshake_ = true;
874 } else {
875 PRErrorCode prerr = PR_GetError();
876 net_error = MapNSSError(prerr);
877
878 // If not done, stay in this state
879 if (net_error == ERR_IO_PENDING) {
880 GotoState(STATE_HANDSHAKE);
881 } else {
882 LOG(ERROR) << "handshake failed; NSS error code " << prerr
883 << ", net_error " << net_error;
884 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
885 CreateNetLogSSLErrorCallback(net_error, prerr));
886 }
887 }
888 return net_error;
889 }
890
891 void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
892 DCHECK_NE(rv, ERR_IO_PENDING);
893 base::ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
894 }
895
896 void SSLServerSocketNSS::DoReadCallback(int rv) {
897 DCHECK(rv != ERR_IO_PENDING);
898 DCHECK(!user_read_callback_.is_null());
899
900 user_read_buf_ = NULL;
901 user_read_buf_len_ = 0;
902 base::ResetAndReturn(&user_read_callback_).Run(rv);
903 }
904
905 void SSLServerSocketNSS::DoWriteCallback(int rv) {
906 DCHECK(rv != ERR_IO_PENDING);
907 DCHECK(!user_write_callback_.is_null());
908
909 user_write_buf_ = NULL;
910 user_write_buf_len_ = 0;
911 base::ResetAndReturn(&user_write_callback_).Run(rv);
912 }
913
914 // static
915 // NSS calls this if an incoming certificate needs to be verified.
916 // Do nothing but return SECSuccess.
917 // This is called only in full handshake mode.
918 // Peer certificate is retrieved in HandshakeCallback() later, which is called
919 // in full handshake mode or in resumption handshake mode.
920 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
921 PRFileDesc* socket,
922 PRBool checksig,
923 PRBool is_server) {
924 // TODO(hclam): Implement.
925 // Tell NSS to not verify the certificate.
926 return SECSuccess;
927 }
928
929 // static
930 // NSS calls this when handshake is completed.
931 // After the SSL handshake is finished we need to verify the certificate.
932 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, void* arg) {
933 // TODO(hclam): Implement.
934 }
935
936 int SSLServerSocketNSS::Init() {
937 // Initialize the NSS SSL library in a threadsafe way. This also
938 // initializes the NSS base library.
939 EnsureNSSSSLInit();
940 if (!NSS_IsInitialized())
941 return ERR_UNEXPECTED;
942
943 EnableSSLServerSockets();
944 return OK;
945 }
946
947 } // namespace
948
949 std::unique_ptr<SSLServerContext> CreateSSLServerContext(
950 X509Certificate* certificate,
951 const crypto::RSAPrivateKey& key,
952 const SSLServerConfig& ssl_server_config) {
953 return std::unique_ptr<SSLServerContext>(
954 new SSLServerContextNSS(certificate, key, ssl_server_config));
955 }
956
957 SSLServerContextNSS::SSLServerContextNSS(
958 X509Certificate* certificate,
959 const crypto::RSAPrivateKey& key,
960 const SSLServerConfig& ssl_server_config)
961 : ssl_server_config_(ssl_server_config),
962 cert_(certificate),
963 key_(key.Copy()) {
964 CHECK(key_);
965 }
966
967 SSLServerContextNSS::~SSLServerContextNSS() {}
968
969 std::unique_ptr<SSLServerSocket> SSLServerContextNSS::CreateSSLServerSocket(
970 std::unique_ptr<StreamSocket> socket) {
971 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
972 << " called yet!";
973
974 return std::unique_ptr<SSLServerSocket>(new SSLServerSocketNSS(
975 std::move(socket), cert_.get(), *key_, ssl_server_config_));
976 }
977
978 void EnableSSLServerSockets() {
979 g_nss_ssl_server_init_singleton.Get();
980 }
981
982 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_server_socket_nss.h ('k') | net/socket/ssl_server_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698