tls: add debugging to native TLS code · nodejs/node@2d5387e (original) (raw)
`@@ -21,6 +21,7 @@
`
21
21
``
22
22
`#include "tls_wrap.h"
`
23
23
`#include "async_wrap-inl.h"
`
``
24
`+
#include "debug_utils.h"
`
24
25
`#include "node_buffer.h" // Buffer
`
25
26
`#include "node_crypto.h" // SecureContext
`
26
27
`#include "node_crypto_bio.h" // NodeBIO
`
`@@ -72,15 +73,18 @@ TLSWrap::TLSWrap(Environment* env,
`
72
73
` stream->PushStreamListener(this);
`
73
74
``
74
75
`InitSSL();
`
``
76
`+
Debug(this, "Created new TLSWrap");
`
75
77
`}
`
76
78
``
77
79
``
78
80
`TLSWrap::~TLSWrap() {
`
``
81
`+
Debug(this, "~TLSWrap()");
`
79
82
` sc_ = nullptr;
`
80
83
`}
`
81
84
``
82
85
``
83
86
`bool TLSWrap::InvokeQueued(int status, const char* error_str) {
`
``
87
`+
Debug(this, "InvokeQueued(%d, %s)", status, error_str);
`
84
88
`if (!write_callback_scheduled_)
`
85
89
`return false;
`
86
90
``
`@@ -95,6 +99,7 @@ bool TLSWrap::InvokeQueued(int status, const char* error_str) {
`
95
99
``
96
100
``
97
101
`void TLSWrap::NewSessionDoneCb() {
`
``
102
`+
Debug(this, "NewSessionDoneCb()");
`
98
103
`Cycle();
`
99
104
`}
`
100
105
``
`@@ -184,6 +189,7 @@ void TLSWrap::Receive(const FunctionCallbackInfo& args) {
`
184
189
`CHECK(Buffer::HasInstance(args[0]));
`
185
190
`char* data = Buffer::Data(args[0]);
`
186
191
`size_t len = Buffer::Length(args[0]);
`
``
192
`+
Debug(wrap, "Receiving %zu bytes injected from JS", len);
`
187
193
``
188
194
`// Copy given buffer entirely or partiall if handle becomes closed
`
189
195
`while (len > 0 && wrap->IsAlive() && !wrap->IsClosing()) {
`
`@@ -230,6 +236,7 @@ void TLSWrap::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
`
230
236
` Local object = c->object();
`
231
237
``
232
238
`if (where & SSL_CB_HANDSHAKE_START) {
`
``
239
`+
Debug(c, "SSLInfoCallback(SSL_CB_HANDSHAKE_START);");
`
233
240
`// Start is tracked to limit number and frequency of renegotiation attempts,
`
234
241
`// since excessive renegotiation may be an attack.
`
235
242
` Local callback;
`
`@@ -245,6 +252,7 @@ void TLSWrap::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
`
245
252
`// sending HelloRequest in OpenSSL-1.1.1.
`
246
253
`// We need to check whether this is in a renegotiation state or not.
`
247
254
`if (where & SSL_CB_HANDSHAKE_DONE && !SSL_renegotiate_pending(ssl)) {
`
``
255
`+
Debug(c, "SSLInfoCallback(SSL_CB_HANDSHAKE_DONE);");
`
248
256
`CHECK(!SSL_renegotiate_pending(ssl));
`
249
257
` Local callback;
`
250
258
``
`@@ -259,31 +267,46 @@ void TLSWrap::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
`
259
267
``
260
268
``
261
269
`void TLSWrap::EncOut() {
`
``
270
`+
Debug(this, "Trying to write encrypted output");
`
``
271
+
262
272
`// Ignore cycling data if ClientHello wasn't yet parsed
`
263
``
`-
if (!hello_parser_.IsEnded())
`
``
273
`+
if (!hello_parser_.IsEnded()) {
`
``
274
`+
Debug(this, "Returning from EncOut(), hello_parser_ active");
`
264
275
`return;
`
``
276
`+
}
`
265
277
``
266
278
`// Write in progress
`
267
``
`-
if (write_size_ != 0)
`
``
279
`+
if (write_size_ != 0) {
`
``
280
`+
Debug(this, "Returning from EncOut(), write currently in progress");
`
268
281
`return;
`
``
282
`+
}
`
269
283
``
270
284
`` // Wait for newSession
callback to be invoked
``
271
``
`-
if (is_awaiting_new_session())
`
``
285
`+
if (is_awaiting_new_session()) {
`
``
286
`+
Debug(this, "Returning from EncOut(), awaiting new session");
`
272
287
`return;
`
``
288
`+
}
`
273
289
``
274
290
`// Split-off queue
`
275
``
`-
if (established_ && current_write_ != nullptr)
`
``
291
`+
if (established_ && current_write_ != nullptr) {
`
``
292
`+
Debug(this, "EncOut() setting write_callback_scheduled_");
`
276
293
` write_callback_scheduled_ = true;
`
``
294
`+
}
`
277
295
``
278
``
`-
if (ssl_ == nullptr)
`
``
296
`+
if (ssl_ == nullptr) {
`
``
297
`+
Debug(this, "Returning from EncOut(), ssl_ == nullptr");
`
279
298
`return;
`
``
299
`+
}
`
280
300
``
281
301
`// No encrypted output ready to write to the underlying stream.
`
282
302
`if (BIO_pending(enc_out_) == 0) {
`
``
303
`+
Debug(this, "No pending encrypted output");
`
283
304
`if (pending_cleartext_input_.empty()) {
`
284
305
`if (!in_dowrite_) {
`
``
306
`+
Debug(this, "No pending cleartext input, not inside DoWrite()");
`
285
307
`InvokeQueued(0);
`
286
308
` } else {
`
``
309
`+
Debug(this, "No pending cleartext input, inside DoWrite()");
`
287
310
`// TODO(@sam-github, @addaleax) If in_dowrite_ is true, appdata was
`
288
311
`// passed to SSL_write(). If we are here, the data was not encrypted to
`
289
312
`// enc_out_ yet. Calling Done() "works", but since the write is not
`
`@@ -313,13 +336,15 @@ void TLSWrap::EncOut() {
`
313
336
`for (size_t i = 0; i < count; i++)
`
314
337
` buf[i] = uv_buf_init(data[i], size[i]);
`
315
338
``
``
339
`+
Debug(this, "Writing %zu buffers to the underlying stream", count);
`
316
340
` StreamWriteResult res = underlying_stream()->Write(bufs, count);
`
317
341
`if (res.err != 0) {
`
318
342
`InvokeQueued(res.err);
`
319
343
`return;
`
320
344
` }
`
321
345
``
322
346
`if (!res.async) {
`
``
347
`+
Debug(this, "Write finished synchronously");
`
323
348
` HandleScope handle_scope(env()->isolate());
`
324
349
``
325
350
`// Simulate asynchronous finishing, TLS cannot handle this at the moment.
`
`@@ -331,21 +356,26 @@ void TLSWrap::EncOut() {
`
331
356
``
332
357
``
333
358
`void TLSWrap::OnStreamAfterWrite(WriteWrap* req_wrap, int status) {
`
``
359
`+
Debug(this, "OnStreamAfterWrite(status = %d)", status);
`
334
360
`if (current_empty_write_ != nullptr) {
`
``
361
`+
Debug(this, "Had empty write");
`
335
362
` WriteWrap* finishing = current_empty_write_;
`
336
363
` current_empty_write_ = nullptr;
`
337
364
` finishing->Done(status);
`
338
365
`return;
`
339
366
` }
`
340
367
``
341
``
`-
if (ssl_ == nullptr)
`
``
368
`+
if (ssl_ == nullptr) {
`
``
369
`+
Debug(this, "ssl_ == nullptr, marking as cancelled");
`
342
370
` status = UV_ECANCELED;
`
``
371
`+
}
`
343
372
``
344
373
`// Handle error
`
345
374
`if (status) {
`
346
``
`-
// Ignore errors after shutdown
`
347
``
`-
if (shutdown_)
`
``
375
`+
if (shutdown_) {
`
``
376
`+
Debug(this, "Ignoring error after shutdown");
`
348
377
`return;
`
``
378
`+
}
`
349
379
``
350
380
`// Notify about error
`
351
381
`InvokeQueued(status);
`
`@@ -446,23 +476,31 @@ Local TLSWrap::GetSSLError(int status, int* err, std::string* msg) {
`
446
476
``
447
477
``
448
478
`void TLSWrap::ClearOut() {
`
``
479
`+
Debug(this, "Trying to read cleartext output");
`
449
480
`// Ignore cycling data if ClientHello wasn't yet parsed
`
450
``
`-
if (!hello_parser_.IsEnded())
`
``
481
`+
if (!hello_parser_.IsEnded()) {
`
``
482
`+
Debug(this, "Returning from ClearOut(), hello_parser_ active");
`
451
483
`return;
`
``
484
`+
}
`
452
485
``
453
486
`// No reads after EOF
`
454
``
`-
if (eof_)
`
``
487
`+
if (eof_) {
`
``
488
`+
Debug(this, "Returning from ClearOut(), EOF reached");
`
455
489
`return;
`
``
490
`+
}
`
456
491
``
457
``
`-
if (ssl_ == nullptr)
`
``
492
`+
if (ssl_ == nullptr) {
`
``
493
`+
Debug(this, "Returning from ClearOut(), ssl_ == nullptr");
`
458
494
`return;
`
``
495
`+
}
`
459
496
``
460
497
` crypto::MarkPopErrorOnReturn mark_pop_error_on_return;
`
461
498
``
462
499
`char out[kClearOutChunkSize];
`
463
500
`int read;
`
464
501
`for (;;) {
`
465
502
`read = SSL_read(ssl_.get(), out, sizeof(out));
`
``
503
`+
Debug(this, "Read %d bytes of cleartext output", read);
`
466
504
``
467
505
`if (read <= 0)
`
468
506
`break;
`
`@@ -480,8 +518,10 @@ void TLSWrap::ClearOut() {
`
480
518
`// Caveat emptor: OnRead() calls into JS land which can result in
`
481
519
`// the SSL context object being destroyed. We have to carefully
`
482
520
`// check that ssl_ != nullptr afterwards.
`
483
``
`-
if (ssl_ == nullptr)
`
``
521
`+
if (ssl_ == nullptr) {
`
``
522
`+
Debug(this, "Returning from read loop, ssl_ == nullptr");
`
484
523
`return;
`
``
524
`+
}
`
485
525
``
486
526
`read -= avail;
`
487
527
` current += avail;
`
`@@ -507,6 +547,7 @@ void TLSWrap::ClearOut() {
`
507
547
`return;
`
508
548
``
509
549
`if (!arg.IsEmpty()) {
`
``
550
`+
Debug(this, "Got SSL error (%d), calling onerror", err);
`
510
551
`// When TLS Alert are stored in wbio,
`
511
552
`// it should be flushed to socket before destroyed.
`
512
553
`if (BIO_pending(enc_out_) != 0)
`
`@@ -519,12 +560,17 @@ void TLSWrap::ClearOut() {
`
519
560
``
520
561
``
521
562
`void TLSWrap::ClearIn() {
`
``
563
`+
Debug(this, "Trying to write cleartext input");
`
522
564
`// Ignore cycling data if ClientHello wasn't yet parsed
`
523
``
`-
if (!hello_parser_.IsEnded())
`
``
565
`+
if (!hello_parser_.IsEnded()) {
`
``
566
`+
Debug(this, "Returning from ClearIn(), hello_parser_ active");
`
524
567
`return;
`
``
568
`+
}
`
525
569
``
526
``
`-
if (ssl_ == nullptr)
`
``
570
`+
if (ssl_ == nullptr) {
`
``
571
`+
Debug(this, "Returning from ClearIn(), ssl_ == nullptr");
`
527
572
`return;
`
``
573
`+
}
`
528
574
``
529
575
` std::vector buffers;
`
530
576
` buffers.swap(pending_cleartext_input_);
`
`@@ -537,13 +583,15 @@ void TLSWrap::ClearIn() {
`
537
583
`size_t avail = buffers[i].len;
`
538
584
`char* data = buffers[i].base;
`
539
585
` written = SSL_write(ssl_.get(), data, avail);
`
``
586
`+
Debug(this, "Writing %zu bytes, written = %d", avail, written);
`
540
587
`CHECK(written == -1 || written == static_cast(avail));
`
541
588
`if (written == -1)
`
542
589
`break;
`
543
590
` }
`
544
591
``
545
592
`// All written
`
546
593
`if (i == buffers.size()) {
`
``
594
`+
Debug(this, "Successfully wrote all data to SSL");
`
547
595
`// We wrote all the buffers, so no writes failed (written < 0 on failure).
`
548
596
`CHECK_GE(written, 0);
`
549
597
`return;
`
`@@ -557,11 +605,13 @@ void TLSWrap::ClearIn() {
`
557
605
` std::string error_str;
`
558
606
` Local arg = GetSSLError(written, &err, &error_str);
`
559
607
`if (!arg.IsEmpty()) {
`
``
608
`+
Debug(this, "Got SSL error (%d)", err);
`
560
609
` write_callback_scheduled_ = true;
`
561
610
`// TODO(@sam-github) Should forward an error object with
`
562
611
`// .code/.function/.etc, if possible.
`
563
612
`InvokeQueued(UV_EPROTO, error_str.c_str());
`
564
613
` } else {
`
``
614
`+
Debug(this, "Pushing back %zu buffers", buffers.size() - i);
`
565
615
`// Push back the not-yet-written pending buffers into their queue.
`
566
616
`// This can be skipped in the error case because no further writes
`
567
617
`// would succeed anyway.
`
`@@ -574,6 +624,17 @@ void TLSWrap::ClearIn() {
`
574
624
`}
`
575
625
``
576
626
``
``
627
`+
std::string TLSWrap::diagnostic_name() const {
`
``
628
`+
std::string name = "TLSWrap ";
`
``
629
`+
if (is_server())
`
``
630
`+
name += "server (";
`
``
631
`+
else
`
``
632
`+
name += "client (";
`
``
633
`+
name += std::to_string(static_cast(get_async_id())) + ")";
`
``
634
`+
return name;
`
``
635
`+
}
`
``
636
+
``
637
+
577
638
`AsyncWrap* TLSWrap::GetAsyncWrap() {
`
578
639
`return static_cast<AsyncWrap*>(this);
`
579
640
`}
`
`@@ -603,13 +664,15 @@ bool TLSWrap::IsClosing() {
`
603
664
``
604
665
``
605
666
`int TLSWrap::ReadStart() {
`
``
667
`+
Debug(this, "ReadStart()");
`
606
668
`if (stream_ != nullptr)
`
607
669
`return stream_->ReadStart();
`
608
670
`return 0;
`
609
671
`}
`
610
672
``
611
673
``
612
674
`int TLSWrap::ReadStop() {
`
``
675
`+
Debug(this, "ReadStop()");
`
613
676
`if (stream_ != nullptr)
`
614
677
`return stream_->ReadStop();
`
615
678
`return 0;
`
`@@ -633,6 +696,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
`
633
696
`size_t count,
`
634
697
`uv_stream_t* send_handle) {
`
635
698
`CHECK_NULL(send_handle);
`
``
699
`+
Debug(this, "DoWrite()");
`
636
700
``
637
701
`if (ssl_ == nullptr) {
`
638
702
`ClearError();
`
`@@ -660,8 +724,10 @@ int TLSWrap::DoWrite(WriteWrap* w,
`
660
724
`// onto the socket, we just want the side-effects. After, make sure the
`
661
725
`// WriteWrap was accepted by the stream, or that we call Done() on it.
`
662
726
`if (empty) {
`
``
727
`+
Debug(this, "Empty write");
`
663
728
`ClearOut();
`
664
729
`if (BIO_pending(enc_out_) == 0) {
`
``
730
`+
Debug(this, "No pending encrypted output, writing to underlying stream");
`
665
731
`CHECK_NULL(current_empty_write_);
`
666
732
` current_empty_write_ = w;
`
667
733
` StreamWriteResult res =
`
`@@ -692,6 +758,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
`
692
758
`for (i = 0; i < count; i++) {
`
693
759
` written = SSL_write(ssl_.get(), bufs[i].base, bufs[i].len);
`
694
760
`CHECK(written == -1 || written == static_cast(bufs[i].len));
`
``
761
`+
Debug(this, "Writing %zu bytes, written = %d", bufs[i].len, written);
`
695
762
`if (written == -1)
`
696
763
`break;
`
697
764
` }
`
`@@ -702,10 +769,12 @@ int TLSWrap::DoWrite(WriteWrap* w,
`
702
769
``
703
770
`// If we stopped writing because of an error, it's fatal, discard the data.
`
704
771
`if (!arg.IsEmpty()) {
`
``
772
`+
Debug(this, "Got SSL error (%d), returning UV_EPROTO", err);
`
705
773
` current_write_ = nullptr;
`
706
774
`return UV_EPROTO;
`
707
775
` }
`
708
776
``
``
777
`+
Debug(this, "Saving %zu buffers for later write", count - i);
`
709
778
`// Otherwise, save unwritten data so it can be written later by ClearIn().
`
710
779
` pending_cleartext_input_.insert(pending_cleartext_input_.end(),
`
711
780
` &bufs[i],
`
`@@ -732,6 +801,7 @@ uv_buf_t TLSWrap::OnStreamAlloc(size_t suggested_size) {
`
732
801
``
733
802
``
734
803
`void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
`
``
804
`+
Debug(this, "Read %zd bytes from underlying stream", nread);
`
735
805
`if (nread < 0) {
`
736
806
`// Error should be emitted only after all data was read
`
737
807
`ClearOut();
`
`@@ -765,6 +835,7 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
`
765
835
`size_t avail = 0;
`
766
836
`uint8_t* data = reinterpret_cast<uint8_t*>(enc_in->Peek(&avail));
`
767
837
`CHECK_IMPLIES(data == nullptr, avail == 0);
`
``
838
`+
Debug(this, "Passing %zu bytes to the hello parser", avail);
`
768
839
`return hello_parser_.Parse(data, avail);
`
769
840
` }
`
770
841
``
`@@ -779,6 +850,7 @@ ShutdownWrap* TLSWrap::CreateShutdownWrap(Local req_wrap_object) {
`
779
850
``
780
851
``
781
852
`int TLSWrap::DoShutdown(ShutdownWrap* req_wrap) {
`
``
853
`+
Debug(this, "DoShutdown()");
`
782
854
` crypto::MarkPopErrorOnReturn mark_pop_error_on_return;
`
783
855
``
784
856
`if (ssl_ && SSL_shutdown(ssl_.get()) == 0)
`
`@@ -844,6 +916,7 @@ void TLSWrap::EnableSessionCallbacks(
`
844
916
`void TLSWrap::DestroySSL(const FunctionCallbackInfo& args) {
`
845
917
` TLSWrap* wrap;
`
846
918
`ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
`
``
919
`+
Debug(wrap, "DestroySSL()");
`
847
920
``
848
921
`// If there is a write happening, mark it as finished.
`
849
922
` wrap->write_callback_scheduled_ = true;
`
`@@ -858,6 +931,7 @@ void TLSWrap::DestroySSL(const FunctionCallbackInfo& args) {
`
858
931
``
859
932
`if (wrap->stream_ != nullptr)
`
860
933
` wrap->stream_->RemoveStreamListener(wrap);
`
``
934
`+
Debug(wrap, "DestroySSL() finished");
`
861
935
`}
`
862
936
``
863
937
``
`@@ -870,6 +944,7 @@ void TLSWrap::EnableCertCb(const FunctionCallbackInfo& args) {
`
870
944
``
871
945
`void TLSWrap::OnClientHelloParseEnd(void* arg) {
`
872
946
` TLSWrap* c = static_cast<TLSWrap*>(arg);
`
``
947
`+
Debug(c, "OnClientHelloParseEnd()");
`
873
948
` c->Cycle();
`
874
949
`}
`
875
950
``