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