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