@@ -115,6 +115,11 @@ void TLSWrap::InitSSL() {
115
115
#endif // SSL_MODE_RELEASE_BUFFERS
116
116
117
117
SSL_set_app_data (ssl_.get (), this );
118
+ // Using InfoCallback isn't how we are supposed to check handshake progress:
119
+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420915993
120
+ //
121
+ // Note on when this gets called on various openssl versions:
122
+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420670544
118
123
SSL_set_info_callback (ssl_.get (), SSLInfoCallback);
119
124
120
125
if (is_server ()) {
@@ -193,6 +198,9 @@ void TLSWrap::Start(const FunctionCallbackInfo<Value>& args) {
193
198
194
199
// Send ClientHello handshake
195
200
CHECK (wrap->is_client ());
201
+ // Seems odd to read when when we want to send, but SSL_read() triggers a
202
+ // handshake if a session isn't established, and handshake will cause
203
+ // encrypted data to become available for output.
196
204
wrap->ClearOut ();
197
205
wrap->EncOut ();
198
206
}
@@ -247,7 +255,7 @@ void TLSWrap::EncOut() {
247
255
return ;
248
256
249
257
// Wait for `newSession` callback to be invoked
250
- if (is_waiting_new_session ())
258
+ if (is_awaiting_new_session ())
251
259
return ;
252
260
253
261
// Split-off queue
@@ -257,7 +265,7 @@ void TLSWrap::EncOut() {
257
265
if (ssl_ == nullptr )
258
266
return ;
259
267
260
- // No data to write
268
+ // No encrypted output ready to write to the underlying stream.
261
269
if (BIO_pending (enc_out_) == 0 ) {
262
270
if (pending_cleartext_input_.empty ())
263
271
InvokeQueued (0 );
@@ -479,13 +487,13 @@ void TLSWrap::ClearOut() {
479
487
}
480
488
481
489
482
- bool TLSWrap::ClearIn () {
490
+ void TLSWrap::ClearIn () {
483
491
// Ignore cycling data if ClientHello wasn't yet parsed
484
492
if (!hello_parser_.IsEnded ())
485
- return false ;
493
+ return ;
486
494
487
495
if (ssl_ == nullptr )
488
- return false ;
496
+ return ;
489
497
490
498
std::vector<uv_buf_t > buffers;
491
499
buffers.swap (pending_cleartext_input_);
@@ -505,8 +513,9 @@ bool TLSWrap::ClearIn() {
505
513
506
514
// All written
507
515
if (i == buffers.size ()) {
516
+ // We wrote all the buffers, so no writes failed (written < 0 on failure).
508
517
CHECK_GE (written, 0 );
509
- return true ;
518
+ return ;
510
519
}
511
520
512
521
// Error or partial write
@@ -518,6 +527,8 @@ bool TLSWrap::ClearIn() {
518
527
Local<Value> arg = GetSSLError (written, &err, &error_str);
519
528
if (!arg.IsEmpty ()) {
520
529
write_callback_scheduled_ = true ;
530
+ // XXX(sam) Should forward an error object with .code/.function/.etc, if
531
+ // possible.
521
532
InvokeQueued (UV_EPROTO, error_str.c_str ());
522
533
} else {
523
534
// Push back the not-yet-written pending buffers into their queue.
@@ -528,7 +539,7 @@ bool TLSWrap::ClearIn() {
528
539
buffers.end ());
529
540
}
530
541
531
- return false ;
542
+ return ;
532
543
}
533
544
534
545
@@ -584,6 +595,7 @@ void TLSWrap::ClearError() {
584
595
}
585
596
586
597
598
+ // Called by StreamBase::Write() to request async write of clear text into SSL.
587
599
int TLSWrap::DoWrite (WriteWrap* w,
588
600
uv_buf_t * bufs,
589
601
size_t count,
@@ -597,18 +609,26 @@ int TLSWrap::DoWrite(WriteWrap* w,
597
609
}
598
610
599
611
bool empty = true ;
600
-
601
- // Empty writes should not go through encryption process
602
612
size_t i;
603
- for (i = 0 ; i < count; i++)
613
+ for (i = 0 ; i < count; i++) {
604
614
if (bufs[i].len > 0 ) {
605
615
empty = false ;
606
616
break ;
607
617
}
618
+ }
619
+
620
+ // We want to trigger a Write() on the underlying stream to drive the stream
621
+ // system, but don't want to encrypt empty buffers into a TLS frame, so see
622
+ // if we can find something to Write().
623
+ // First, call ClearOut(). It does an SSL_read(), which might cause handshake
624
+ // or other internal messages to be encrypted. If it does, write them later
625
+ // with EncOut().
626
+ // If there is still no encrypted output, call Write(bufs) on the underlying
627
+ // stream. Since the bufs are empty, it won't actually write non-TLS data
628
+ // onto the socket, we just want the side-effects. After, make sure the
629
+ // WriteWrap was accepted by the stream, or that we call Done() on it.
608
630
if (empty) {
609
631
ClearOut ();
610
- // However, if there is any data that should be written to the socket,
611
- // the callback should not be invoked immediately
612
632
if (BIO_pending (enc_out_) == 0 ) {
613
633
CHECK_NULL (current_empty_write_);
614
634
current_empty_write_ = w;
@@ -628,7 +648,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
628
648
CHECK_NULL (current_write_);
629
649
current_write_ = w;
630
650
631
- // Write queued data
651
+ // Write encrypted data to underlying stream and call Done().
632
652
if (empty) {
633
653
EncOut ();
634
654
return 0 ;
@@ -647,17 +667,20 @@ int TLSWrap::DoWrite(WriteWrap* w,
647
667
if (i != count) {
648
668
int err;
649
669
Local<Value> arg = GetSSLError (written, &err, &error_);
670
+
671
+ // If we stopped writing because of an error, it's fatal, discard the data.
650
672
if (!arg.IsEmpty ()) {
651
673
current_write_ = nullptr ;
652
674
return UV_EPROTO;
653
675
}
654
676
677
+ // Otherwise, save unwritten data so it can be written later by ClearIn().
655
678
pending_cleartext_input_.insert (pending_cleartext_input_.end (),
656
679
&bufs[i],
657
680
&bufs[count]);
658
681
}
659
682
660
- // Try writing data immediately
683
+ // Write any encrypted/handshake output that may be ready.
661
684
EncOut ();
662
685
663
686
return 0 ;
@@ -689,17 +712,20 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
689
712
return ;
690
713
}
691
714
692
- // Only client connections can receive data
693
715
if (ssl_ == nullptr ) {
694
716
EmitRead (UV_EPROTO);
695
717
return ;
696
718
}
697
719
698
- // Commit read data
720
+ // Commit the amount of data actually read into the peeked/allocated buffer
721
+ // from the underlying stream.
699
722
crypto::NodeBIO* enc_in = crypto::NodeBIO::FromBIO (enc_in_);
700
723
enc_in->Commit (nread);
701
724
702
- // Parse ClientHello first
725
+ // Parse ClientHello first, if we need to. It's only parsed if session event
726
+ // listeners are used on the server side. "ended" is the initial state, so
727
+ // can mean parsing was never started, or that parsing is finished. Either
728
+ // way, ended means we can give the buffered data to SSL.
703
729
if (!hello_parser_.IsEnded ()) {
704
730
size_t avail = 0 ;
705
731
uint8_t * data = reinterpret_cast <uint8_t *>(enc_in->Peek (&avail));
0 commit comments