@@ -116,6 +116,11 @@ void TLSWrap::InitSSL() {
116
116
#endif // SSL_MODE_RELEASE_BUFFERS
117
117
118
118
SSL_set_app_data (ssl_.get (), this );
119
+ // Using InfoCallback isn't how we are supposed to check handshake progress:
120
+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420915993
121
+ //
122
+ // Note on when this gets called on various openssl versions:
123
+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420670544
119
124
SSL_set_info_callback (ssl_.get (), SSLInfoCallback);
120
125
121
126
if (is_server ()) {
@@ -194,6 +199,9 @@ void TLSWrap::Start(const FunctionCallbackInfo<Value>& args) {
194
199
195
200
// Send ClientHello handshake
196
201
CHECK (wrap->is_client ());
202
+ // Seems odd to read when when we want to send, but SSL_read() triggers a
203
+ // handshake if a session isn't established, and handshake will cause
204
+ // encrypted data to become available for output.
197
205
wrap->ClearOut ();
198
206
wrap->EncOut ();
199
207
}
@@ -243,7 +251,7 @@ void TLSWrap::EncOut() {
243
251
return ;
244
252
245
253
// Wait for `newSession` callback to be invoked
246
- if (is_waiting_new_session ())
254
+ if (is_awaiting_new_session ())
247
255
return ;
248
256
249
257
// Split-off queue
@@ -253,7 +261,7 @@ void TLSWrap::EncOut() {
253
261
if (ssl_ == nullptr )
254
262
return ;
255
263
256
- // No data to write
264
+ // No encrypted output ready to write to the underlying stream.
257
265
if (BIO_pending (enc_out_) == 0 ) {
258
266
if (pending_cleartext_input_.empty ())
259
267
InvokeQueued (0 );
@@ -442,13 +450,13 @@ void TLSWrap::ClearOut() {
442
450
}
443
451
444
452
445
- bool TLSWrap::ClearIn () {
453
+ void TLSWrap::ClearIn () {
446
454
// Ignore cycling data if ClientHello wasn't yet parsed
447
455
if (!hello_parser_.IsEnded ())
448
- return false ;
456
+ return ;
449
457
450
458
if (ssl_ == nullptr )
451
- return false ;
459
+ return ;
452
460
453
461
std::vector<uv_buf_t > buffers;
454
462
buffers.swap (pending_cleartext_input_);
@@ -468,8 +476,9 @@ bool TLSWrap::ClearIn() {
468
476
469
477
// All written
470
478
if (i == buffers.size ()) {
479
+ // We wrote all the buffers, so no writes failed (written < 0 on failure).
471
480
CHECK_GE (written, 0 );
472
- return true ;
481
+ return ;
473
482
}
474
483
475
484
// Error or partial write
@@ -481,6 +490,8 @@ bool TLSWrap::ClearIn() {
481
490
Local<Value> arg = GetSSLError (written, &err, &error_str);
482
491
if (!arg.IsEmpty ()) {
483
492
write_callback_scheduled_ = true ;
493
+ // XXX(sam) Should forward an error object with .code/.function/.etc, if
494
+ // possible.
484
495
InvokeQueued (UV_EPROTO, error_str.c_str ());
485
496
} else {
486
497
// Push back the not-yet-written pending buffers into their queue.
@@ -491,7 +502,7 @@ bool TLSWrap::ClearIn() {
491
502
buffers.end ());
492
503
}
493
504
494
- return false ;
505
+ return ;
495
506
}
496
507
497
508
@@ -547,6 +558,7 @@ void TLSWrap::ClearError() {
547
558
}
548
559
549
560
561
+ // Called by StreamBase::Write() to request async write of clear text into SSL.
550
562
int TLSWrap::DoWrite (WriteWrap* w,
551
563
uv_buf_t * bufs,
552
564
size_t count,
@@ -560,18 +572,26 @@ int TLSWrap::DoWrite(WriteWrap* w,
560
572
}
561
573
562
574
bool empty = true ;
563
-
564
- // Empty writes should not go through encryption process
565
575
size_t i;
566
- for (i = 0 ; i < count; i++)
576
+ for (i = 0 ; i < count; i++) {
567
577
if (bufs[i].len > 0 ) {
568
578
empty = false ;
569
579
break ;
570
580
}
581
+ }
582
+
583
+ // We want to trigger a Write() on the underlying stream to drive the stream
584
+ // system, but don't want to encrypt empty buffers into a TLS frame, so see
585
+ // if we can find something to Write().
586
+ // First, call ClearOut(). It does an SSL_read(), which might cause handshake
587
+ // or other internal messages to be encrypted. If it does, write them later
588
+ // with EncOut().
589
+ // If there is still no encrypted output, call Write(bufs) on the underlying
590
+ // stream. Since the bufs are empty, it won't actually write non-TLS data
591
+ // onto the socket, we just want the side-effects. After, make sure the
592
+ // WriteWrap was accepted by the stream, or that we call Done() on it.
571
593
if (empty) {
572
594
ClearOut ();
573
- // However, if there is any data that should be written to the socket,
574
- // the callback should not be invoked immediately
575
595
if (BIO_pending (enc_out_) == 0 ) {
576
596
CHECK_NULL (current_empty_write_);
577
597
current_empty_write_ = w;
@@ -591,7 +611,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
591
611
CHECK_NULL (current_write_);
592
612
current_write_ = w;
593
613
594
- // Write queued data
614
+ // Write encrypted data to underlying stream and call Done().
595
615
if (empty) {
596
616
EncOut ();
597
617
return 0 ;
@@ -610,17 +630,20 @@ int TLSWrap::DoWrite(WriteWrap* w,
610
630
if (i != count) {
611
631
int err;
612
632
Local<Value> arg = GetSSLError (written, &err, &error_);
633
+
634
+ // If we stopped writing because of an error, it's fatal, discard the data.
613
635
if (!arg.IsEmpty ()) {
614
636
current_write_ = nullptr ;
615
637
return UV_EPROTO;
616
638
}
617
639
640
+ // Otherwise, save unwritten data so it can be written later by ClearIn().
618
641
pending_cleartext_input_.insert (pending_cleartext_input_.end (),
619
642
&bufs[i],
620
643
&bufs[count]);
621
644
}
622
645
623
- // Try writing data immediately
646
+ // Write any encrypted/handshake output that may be ready.
624
647
EncOut ();
625
648
626
649
return 0 ;
@@ -652,17 +675,20 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
652
675
return ;
653
676
}
654
677
655
- // Only client connections can receive data
656
678
if (ssl_ == nullptr ) {
657
679
EmitRead (UV_EPROTO);
658
680
return ;
659
681
}
660
682
661
- // Commit read data
683
+ // Commit the amount of data actually read into the peeked/allocated buffer
684
+ // from the underlying stream.
662
685
crypto::NodeBIO* enc_in = crypto::NodeBIO::FromBIO (enc_in_);
663
686
enc_in->Commit (nread);
664
687
665
- // Parse ClientHello first
688
+ // Parse ClientHello first, if we need to. It's only parsed if session event
689
+ // listeners are used on the server side. "ended" is the initial state, so
690
+ // can mean parsing was never started, or that parsing is finished. Either
691
+ // way, ended means we can give the buffered data to SSL.
666
692
if (!hello_parser_.IsEnded ()) {
667
693
size_t avail = 0 ;
668
694
uint8_t * data = reinterpret_cast <uint8_t *>(enc_in->Peek (&avail));
0 commit comments