Flutter Engine
The Flutter Engine
secure_socket_filter.cc
Go to the documentation of this file.
1// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
6
8
9#include <openssl/bio.h>
10#include <openssl/ssl.h>
11#include <openssl/x509.h>
12
13#include "bin/lockers.h"
16#include "bin/socket_base.h"
17#include "platform/syslog.h"
19
20// Return the error from the containing function if handle is an error handle.
21#define RETURN_IF_ERROR(handle) \
22 { \
23 Dart_Handle __handle = handle; \
24 if (Dart_IsError((__handle))) { \
25 return __handle; \
26 } \
27 }
28
29namespace dart {
30namespace bin {
31
32bool SSLFilter::library_initialized_ = false;
33// To protect library initialization.
34Mutex* SSLFilter::mutex_ = nullptr;
37
39 ASSERT(SSLFilter::mutex_ == nullptr);
40 SSLFilter::mutex_ = new Mutex();
41}
42
44 ASSERT(SSLFilter::mutex_ != nullptr);
45 delete SSLFilter::mutex_;
46 SSLFilter::mutex_ = nullptr;
47}
48
49const intptr_t SSLFilter::kInternalBIOSize = 10 * KB;
50const intptr_t SSLFilter::kApproximateSize =
51 sizeof(SSLFilter) + (2 * SSLFilter::kInternalBIOSize);
52
54 SSLFilter* filter = nullptr;
56 ASSERT(Dart_IsInstance(dart_this));
59 reinterpret_cast<intptr_t*>(&filter)));
60 if (filter == nullptr) {
62 DartUtils::NewInternalError("No native peer")));
63 }
64 return filter;
65}
66
67static void DeleteFilter(void* isolate_data, void* context_pointer) {
68 SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
69 filter->Release();
70}
71
73 ASSERT(filter != nullptr);
75 RETURN_IF_ERROR(dart_this);
76 ASSERT(Dart_IsInstance(dart_this));
79 reinterpret_cast<intptr_t>(filter));
80 RETURN_IF_ERROR(err);
81 Dart_NewFinalizableHandle(dart_this, reinterpret_cast<void*>(filter),
83 return Dart_Null();
84}
85
88 SSLFilter* filter = new SSLFilter();
89 Dart_Handle err = SetFilter(args, filter);
90 if (Dart_IsError(err)) {
91 filter->Release();
93 }
94 err = filter->Init(dart_this);
95 if (Dart_IsError(err)) {
96 // The finalizer was set up by SetFilter. It will delete `filter` if there
97 // is an error.
98 filter->Destroy();
100 }
101}
102
104 Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
107 bool request_client_certificate =
109 bool require_client_certificate =
111 Dart_Handle protocols_handle = ThrowIfError(Dart_GetNativeArgument(args, 6));
112
113 const char* host_name = nullptr;
114 // TODO(whesse): Is truncating a Dart string containing \0 what we want?
115 ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
116
117 SSLCertContext* context = nullptr;
118 if (!Dart_IsNull(context_object)) {
121 reinterpret_cast<intptr_t*>(&context)));
122 }
123
124 // The protocols_handle is guaranteed to be a valid Uint8List.
125 // It will have the correct length encoding of the protocols array.
126 ASSERT(!Dart_IsNull(protocols_handle));
127 GetFilter(args)->Connect(host_name, context, is_server,
128 request_client_certificate,
129 require_client_certificate, protocols_handle);
130}
131
133 SSLFilter* filter = GetFilter(args);
134 // There are two paths that can clean up an SSLFilter object. First,
135 // there is this explicit call to Destroy(), called from
136 // _SecureFilter.destroy() in Dart code. After a call to destroy(), the Dart
137 // code maintains the invariant that there will be no further SSLFilter
138 // requests sent to the IO Service. Therefore, the internals of the SSLFilter
139 // are safe to deallocate, but not the SSLFilter itself, which is already
140 // set up to be cleaned up by the finalizer.
141 //
142 // The second path is through the finalizer, which we have to do in case
143 // some mishap prevents a call to _SecureFilter.destroy().
144 filter->Destroy();
145}
146
150
151 Dart_Port port_id;
153 int result = GetFilter(args)->Handshake(port_id);
155}
156
158 GetFilter(args)->MarkAsTrusted(args);
159}
160
163// This is to be used only in conjunction with certificate trust evaluator
164// running asynchronously, which is only used on mac/ios at the moment.
165#if !defined(DART_HOST_OS_MACOS)
166 FATAL("This is to be used only on mac/ios platforms");
167#endif
168 intptr_t x509_pointer = DartUtils::GetNativeIntptrArgument(args, 0);
169 X509* x509 = reinterpret_cast<X509*>(x509_pointer);
171}
172
175 GetFilter(args)->GetSelectedProtocol(args);
176}
177
180 Dart_Handle handshake_complete =
182 if (!Dart_IsClosure(handshake_complete)) {
184 "Illegal argument to RegisterHandshakeCompleteCallback"));
185 }
186 GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
187}
188
194 "Illegal argument to RegisterBadCertificateCallback"));
195 }
196 GetFilter(args)->RegisterBadCertificateCallback(callback);
197}
198
202
203 Dart_Port port_id;
205 GetFilter(args)->RegisterKeyLogPort(port_id);
206}
207
209 Dart_Handle cert = ThrowIfError(GetFilter(args)->PeerCertificate());
211}
212
214 SSLFilter* filter = GetFilter(args);
215 // This filter pointer is passed to the IO Service thread. The IO Service
216 // thread must Release() the pointer when it is done with it.
217 filter->Retain();
218 intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
219 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
220}
221
222/**
223 * Pushes data through the SSL filter, reading and writing from circular
224 * buffers shared with Dart.
225 *
226 * The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
227 * pass encrypted and plaintext data to and from the C++ SSLFilter object.
228 *
229 * ProcessFilter is called with a CObject array containing the pointer to
230 * the SSLFilter, encoded as an int, and the start and end positions of the
231 * valid data in the four circular buffers. The function only reads from
232 * the valid data area of the input buffers, and only writes to the free
233 * area of the output buffers. The function returns the new start and end
234 * positions in the buffers, but it only updates start for input buffers, and
235 * end for output buffers. Therefore, the Dart thread can simultaneously
236 * write to the free space and end pointer of input buffers, and read from
237 * the data space of output buffers, and modify the start pointer.
238 *
239 * When ProcessFilter returns, the Dart thread is responsible for combining
240 * the updated pointers from Dart and C++, to make the new valid state of
241 * the circular buffer.
242 */
244 CObjectIntptr filter_object(request[0]);
245 SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
247
248 bool in_handshake = CObjectBool(request[1]).Value();
249 int starts[SSLFilter::kNumBuffers];
250 int ends[SSLFilter::kNumBuffers];
251 for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
252 starts[i] = CObjectInt32(request[2 * i + 2]).Value();
253 ends[i] = CObjectInt32(request[2 * i + 3]).Value();
254 }
255
256 if (filter->ProcessAllBuffers(starts, ends, in_handshake)) {
259 for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
260 result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
261 result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
262 }
263 return result;
264 } else {
265 int32_t error_code = static_cast<int32_t>(ERR_peek_error());
267 SecureSocketUtils::FetchErrorString(filter->ssl_, &error_string);
269 result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code)));
270 result->SetAt(1,
271 new CObjectString(CObject::NewString(error_string.buffer())));
272 return result;
273 }
274}
275
276bool SSLFilter::ProcessAllBuffers(int starts[kNumBuffers],
277 int ends[kNumBuffers],
278 bool in_handshake) {
279 for (int i = 0; i < kNumBuffers; ++i) {
280 if (in_handshake && (i == kReadPlaintext || i == kWritePlaintext)) continue;
281 int start = starts[i];
282 int end = ends[i];
283 int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
284 if (start < 0 || end < 0 || start >= size || end >= size) {
285 FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
286 }
287 switch (i) {
288 case kReadPlaintext:
289 case kWriteEncrypted:
290 // Write data to the circular buffer's free space. If the buffer
291 // is full, neither if statement is executed and nothing happens.
292 if (start <= end) {
293 // If the free space may be split into two segments,
294 // then the first is [end, size), unless start == 0.
295 // Then, since the last free byte is at position start - 2,
296 // the interval is [end, size - 1).
297 int buffer_end = (start == 0) ? size - 1 : size;
298 int bytes = (i == kReadPlaintext)
299 ? ProcessReadPlaintextBuffer(end, buffer_end)
300 : ProcessWriteEncryptedBuffer(end, buffer_end);
301 if (bytes < 0) return false;
302 end += bytes;
303 ASSERT(end <= size);
304 if (end == size) end = 0;
305 }
306 if (start > end + 1) {
307 int bytes = (i == kReadPlaintext)
310 if (bytes < 0) return false;
311 end += bytes;
312 ASSERT(end < start);
313 }
314 ends[i] = end;
315 break;
316 case kReadEncrypted:
317 case kWritePlaintext:
318 // Read/Write data from circular buffer. If the buffer is empty,
319 // neither if statement's condition is true.
320 if (end < start) {
321 // Data may be split into two segments. In this case,
322 // the first is [start, size).
323 int bytes = (i == kReadEncrypted)
326 if (bytes < 0) return false;
327 start += bytes;
328 ASSERT(start <= size);
329 if (start == size) start = 0;
330 }
331 if (start < end) {
332 int bytes = (i == kReadEncrypted)
335 if (bytes < 0) return false;
336 start += bytes;
337 ASSERT(start <= end);
338 }
339 starts[i] = start;
340 break;
341 default:
342 UNREACHABLE();
343 }
344 }
345 return true;
346}
347
349 if (!library_initialized_) {
351 }
352 ASSERT(string_start_ == nullptr);
353 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
354 ASSERT(string_start_ != nullptr);
355 ASSERT(string_length_ == nullptr);
356 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
357 ASSERT(string_length_ != nullptr);
358 ASSERT(bad_certificate_callback_ == nullptr);
359 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
360 ASSERT(bad_certificate_callback_ != nullptr);
361 // Caller handles cleanup on an error.
362 return InitializeBuffers(dart_this);
363}
364
365Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
366 // Create SSLFilter buffers as ExternalUint8Array objects.
367 Dart_Handle buffers_string = DartUtils::NewString("buffers");
368 RETURN_IF_ERROR(buffers_string);
369 Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
370 RETURN_IF_ERROR(dart_buffers_object);
371 Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
372 RETURN_IF_ERROR(secure_filter_impl_type);
373 Dart_Handle size_string = DartUtils::NewString("SIZE");
374 RETURN_IF_ERROR(size_string);
375 Dart_Handle dart_buffer_size =
376 Dart_GetField(secure_filter_impl_type, size_string);
377 RETURN_IF_ERROR(dart_buffer_size);
378
379 int64_t buffer_size = 0;
380 Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
381 RETURN_IF_ERROR(err);
382
383 Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
384 RETURN_IF_ERROR(encrypted_size_string);
385
386 Dart_Handle dart_encrypted_buffer_size =
387 Dart_GetField(secure_filter_impl_type, encrypted_size_string);
388 RETURN_IF_ERROR(dart_encrypted_buffer_size);
389
390 int64_t encrypted_buffer_size = 0;
391 err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
392 RETURN_IF_ERROR(err);
393
394 if (buffer_size <= 0 || buffer_size > 1 * MB) {
395 FATAL("Invalid buffer size in _ExternalBuffer");
396 }
397 if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
398 FATAL("Invalid encrypted buffer size in _ExternalBuffer");
399 }
400 buffer_size_ = static_cast<int>(buffer_size);
401 encrypted_buffer_size_ = static_cast<int>(encrypted_buffer_size);
402
403 Dart_Handle data_identifier = DartUtils::NewString("data");
404 RETURN_IF_ERROR(data_identifier);
405
406 for (int i = 0; i < kNumBuffers; i++) {
407 int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
408 buffers_[i] = new uint8_t[size];
409 ASSERT(buffers_[i] != nullptr);
410 memset(buffers_[i], 0, size);
411 dart_buffer_objects_[i] = nullptr;
412 }
413
415 for (int i = 0; i < kNumBuffers; ++i) {
416 int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
417 result = Dart_ListGetAt(dart_buffers_object, i);
418 if (Dart_IsError(result)) {
419 break;
420 }
421
422 dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
423 ASSERT(dart_buffer_objects_[i] != nullptr);
426 if (Dart_IsError(data)) {
427 result = data;
428 break;
429 }
430 result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
431 if (Dart_IsError(result)) {
432 break;
433 }
434 result = Dart_SetField(result, data_identifier, data);
435 if (Dart_IsError(result)) {
436 break;
437 }
438 }
439
440 // Caller handles cleanup on an error.
441 return result;
442}
443
445 ASSERT(nullptr == handshake_complete_);
446 handshake_complete_ = Dart_NewPersistentHandle(complete);
447
448 ASSERT(handshake_complete_ != nullptr);
449}
450
452 ASSERT(bad_certificate_callback_ != nullptr);
453 Dart_DeletePersistentHandle(bad_certificate_callback_);
454 bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
455 ASSERT(bad_certificate_callback_ != nullptr);
456}
457
459 X509* ca = SSL_get_peer_certificate(ssl_);
460 if (ca == nullptr) {
461 return Dart_Null();
462 }
464}
465
467 key_log_port_ = key_log_port;
468}
469
471 MutexLocker locker(mutex_);
472 if (!library_initialized_) {
473 SSL_library_init();
475 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
478 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
480 library_initialized_ = true;
481 }
482}
483
484void SSLFilter::Connect(const char* hostname,
485 SSLCertContext* context,
486 bool is_server,
487 bool request_client_certificate,
488 bool require_client_certificate,
489 Dart_Handle protocols_handle) {
490 is_server_ = is_server;
491 if (in_handshake_) {
492 FATAL("Connect called twice on the same _SecureFilter.");
493 }
494
495 int status;
496 int error;
497 BIO* ssl_side;
498 status = BIO_new_bio_pair(&ssl_side, kInternalBIOSize, &socket_side_,
499 kInternalBIOSize);
500 SecureSocketUtils::CheckStatusSSL(status, "TlsException", "BIO_new_bio_pair",
501 ssl_);
502
503 ASSERT(context != nullptr);
504 ASSERT(context->context() != nullptr);
505 ssl_ = SSL_new(context->context());
506 SSL_set_bio(ssl_, ssl_side, ssl_side);
507 SSL_set_mode(ssl_, SSL_MODE_AUTO_RETRY); // TODO(whesse): Is this right?
508 SSL_set_ex_data(ssl_, filter_ssl_index, this);
509
510 if (context->allow_tls_renegotiation()) {
511 SSL_set_renegotiate_mode(ssl_, ssl_renegotiate_freely);
512 }
513 context->RegisterCallbacks(ssl_);
514 SSL_set_ex_data(ssl_, ssl_cert_context_index, context);
515
516 TrustEvaluateHandlerFunc trust_evaluate_handler =
517 context->GetTrustEvaluateHandler();
518 if (trust_evaluate_handler != nullptr) {
519 trust_evaluate_reply_port_ = Dart_NewNativePort(
520 "SSLCertContextTrustEvaluate", trust_evaluate_handler,
521 /*handle_concurrently=*/false);
522 }
523 if (is_server_) {
524 int certificate_mode =
525 request_client_certificate ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
526 if (require_client_certificate) {
527 certificate_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
528 }
529 SSL_set_verify(ssl_, certificate_mode, nullptr);
530 } else {
531 SSLCertContext::SetAlpnProtocolList(protocols_handle, ssl_, nullptr, false);
532 status = SSL_set_tlsext_host_name(ssl_, hostname);
533 SecureSocketUtils::CheckStatusSSL(status, "TlsException",
534 "Set SNI host name", ssl_);
535 // Sets the hostname in the certificate-checking object, so it is checked
536 // against the certificate presented by the server.
537 X509_VERIFY_PARAM* certificate_checking_parameters = SSL_get0_param(ssl_);
538 hostname_ = Utils::StrDup(hostname);
539 X509_VERIFY_PARAM_set_flags(
540 certificate_checking_parameters,
541 X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_TRUSTED_FIRST);
542 X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0);
543
544 // Use different check depending on whether the hostname is an IP address
545 // or a DNS name.
546 if (SocketBase::IsValidAddress(hostname_)) {
547 status = X509_VERIFY_PARAM_set1_ip_asc(certificate_checking_parameters,
548 hostname_);
549 } else {
550 status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters,
551 hostname_, strlen(hostname_));
552 }
554 status, "TlsException", "Set hostname for certificate checking", ssl_);
555 }
556 // Make the connection:
557 if (is_server_) {
558 status = SSL_accept(ssl_);
559 if (SSL_LOG_STATUS) {
560 Syslog::Print("SSL_accept status: %d\n", status);
561 }
562 if (status != 1) {
563 // TODO(whesse): expect a needs-data error here. Handle other errors.
564 error = SSL_get_error(ssl_, status);
565 if (SSL_LOG_STATUS) {
566 Syslog::Print("SSL_accept error: %d\n", error);
567 }
568 }
569 } else {
570 status = SSL_connect(ssl_);
571 if (SSL_LOG_STATUS) {
572 Syslog::Print("SSL_connect status: %d\n", status);
573 }
574 if (status != 1) {
575 // TODO(whesse): expect a needs-data error here. Handle other errors.
576 error = SSL_get_error(ssl_, status);
577 if (SSL_LOG_STATUS) {
578 Syslog::Print("SSL_connect error: %d\n", error);
579 }
580 }
581 }
582 // We don't expect certificate evaluation on first attempt,
583 // we expect requests for more bytes, therefore we could get away
584 // with passing illegal port.
586}
587
589 intptr_t certificate_pointer = DartUtils::GetNativeIntptrArgument(args, 1);
590 ASSERT(certificate_pointer != 0);
591 certificate_trust_state_.reset(
592 new X509TrustState(reinterpret_cast<X509*>(certificate_pointer),
594 if (SSL_LOG_STATUS) {
595 Syslog::Print("Mark %p as %strusted certificate\n",
596 certificate_trust_state_->x509(),
597 certificate_trust_state_->is_trusted() ? "" : "not ");
598 }
599}
600
602 // Set reply port to be used by CertificateVerificationCallback
603 // invoked by SSL_do_handshake: this is where results of
604 // certificate evaluation will be communicated to.
605 reply_port_ = reply_port;
606
607 // Try and push handshake along.
608 int status = SSL_do_handshake(ssl_);
609 int error = SSL_get_error(ssl_, status);
610 if (error == SSL_ERROR_WANT_CERTIFICATE_VERIFY) {
611 return SSL_ERROR_WANT_CERTIFICATE_VERIFY;
612 }
613 if (callback_error != nullptr) {
614 // The SSL_do_handshake will try performing a handshake and might call one
615 // or both of:
616 // SSLCertContext::KeyLogCallback
617 // SSLCertContext::CertificateCallback
618 //
619 // If either of those functions fail, and this.callback_error has not
620 // already been set, then they will set this.callback_error to an error
621 // handle i.e. only the first error will be captured and propagated.
623 }
624 if (SSL_want_write(ssl_) || SSL_want_read(ssl_)) {
625 in_handshake_ = true;
626 return error;
627 }
629 status, "HandshakeException",
630 is_server_ ? "Handshake error in server" : "Handshake error in client",
631 ssl_);
632 // Handshake succeeded.
633 if (in_handshake_) {
634 // TODO(24071): Check return value of SSL_get_verify_result, this
635 // should give us the hostname check.
636 int result = SSL_get_verify_result(ssl_);
637 if (SSL_LOG_STATUS) {
638 Syslog::Print("Handshake verification status: %d\n", result);
639 X509* peer_certificate = SSL_get_peer_certificate(ssl_);
640 if (peer_certificate == nullptr) {
641 Syslog::Print("No peer certificate received\n");
642 } else {
643 X509_NAME* s_name = X509_get_subject_name(peer_certificate);
644 printf("Peer certificate SN: ");
645 X509_NAME_print_ex_fp(stdout, s_name, 4, 0);
646 printf("\n");
647 }
648 }
650 Dart_HandleFromPersistent(handshake_complete_), 0, nullptr));
651 in_handshake_ = false;
652 }
653
654 return error;
655}
656
658 const uint8_t* protocol;
659 unsigned length;
660 SSL_get0_alpn_selected(ssl_, &protocol, &length);
661 if (length == 0) {
663 } else {
665 }
666}
667
669 if (ssl_ != nullptr) {
670 SSL_free(ssl_);
671 ssl_ = nullptr;
672 }
673 if (socket_side_ != nullptr) {
674 BIO_free(socket_side_);
675 socket_side_ = nullptr;
676 }
677 if (hostname_ != nullptr) {
678 free(hostname_);
679 hostname_ = nullptr;
680 }
681 for (int i = 0; i < kNumBuffers; ++i) {
682 if (buffers_[i] != nullptr) {
683 delete[] buffers_[i];
684 buffers_[i] = nullptr;
685 }
686 }
687}
688
691}
692
694 for (int i = 0; i < kNumBuffers; ++i) {
695 if (dart_buffer_objects_[i] != nullptr) {
696 Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
697 dart_buffer_objects_[i] = nullptr;
698 }
699 }
700 if (string_start_ != nullptr) {
701 Dart_DeletePersistentHandle(string_start_);
702 string_start_ = nullptr;
703 }
704 if (string_length_ != nullptr) {
705 Dart_DeletePersistentHandle(string_length_);
706 string_length_ = nullptr;
707 }
708 if (handshake_complete_ != nullptr) {
709 Dart_DeletePersistentHandle(handshake_complete_);
710 handshake_complete_ = nullptr;
711 }
712 if (bad_certificate_callback_ != nullptr) {
713 Dart_DeletePersistentHandle(bad_certificate_callback_);
714 bad_certificate_callback_ = nullptr;
715 }
716 if (trust_evaluate_reply_port_ != ILLEGAL_PORT) {
717 Dart_CloseNativePort(trust_evaluate_reply_port_);
718 trust_evaluate_reply_port_ = ILLEGAL_PORT;
719 }
721}
722
723/* Read decrypted data from the filter to the circular buffer */
725 int length = end - start;
726 int bytes_processed = 0;
727 if (SSL_LOG_DATA) {
728 Syslog::Print("Entering ProcessReadPlaintextBuffer with %d bytes\n",
729 length);
730 }
731 if (length > 0) {
732 bytes_processed = SSL_read(
733 ssl_, reinterpret_cast<char*>((buffers_[kReadPlaintext] + start)),
734 length);
735 if (bytes_processed < 0) {
736 int error = SSL_get_error(ssl_, bytes_processed);
737 if (SSL_LOG_DATA) {
738 Syslog::Print("SSL_read returned error %d\n", error);
739 }
740 switch (error) {
741 case SSL_ERROR_SYSCALL:
742 case SSL_ERROR_SSL:
743 return -1;
744 default:
745 break;
746 }
747 bytes_processed = 0;
748 }
749 }
750 if (SSL_LOG_DATA) {
751 Syslog::Print("Leaving ProcessReadPlaintextBuffer read %d bytes\n",
752 bytes_processed);
753 }
754 return bytes_processed;
755}
756
758 int length = end - start;
759 if (SSL_LOG_DATA) {
760 Syslog::Print("Entering ProcessWritePlaintextBuffer with %d bytes\n",
761 length);
762 }
763 int bytes_processed =
764 SSL_write(ssl_, buffers_[kWritePlaintext] + start, length);
765 if (bytes_processed < 0) {
766 if (SSL_LOG_DATA) {
767 Syslog::Print("SSL_write returned error %d\n", bytes_processed);
768 }
769 return 0;
770 }
771 if (SSL_LOG_DATA) {
772 Syslog::Print("Leaving ProcessWritePlaintextBuffer wrote %d bytes\n",
773 bytes_processed);
774 }
775 return bytes_processed;
776}
777
778/* Read encrypted data from the circular buffer to the filter */
780 int length = end - start;
781 if (SSL_LOG_DATA) {
782 Syslog::Print("Entering ProcessReadEncryptedBuffer with %d bytes\n",
783 length);
784 }
785 int bytes_processed = 0;
786 if (length > 0) {
787 bytes_processed =
788 BIO_write(socket_side_, buffers_[kReadEncrypted] + start, length);
789 if (bytes_processed <= 0) {
790 bool retry = BIO_should_retry(socket_side_) != 0;
791 if (!retry) {
792 if (SSL_LOG_DATA) {
793 Syslog::Print("BIO_write failed in ReadEncryptedBuffer\n");
794 }
795 }
796 bytes_processed = 0;
797 }
798 }
799 if (SSL_LOG_DATA) {
800 Syslog::Print("Leaving ProcessReadEncryptedBuffer read %d bytes\n",
801 bytes_processed);
802 }
803 return bytes_processed;
804}
805
807 int length = end - start;
808 int bytes_processed = 0;
809 if (SSL_LOG_DATA) {
810 Syslog::Print("Entering ProcessWriteEncryptedBuffer with %d bytes\n",
811 length);
812 }
813 if (length > 0) {
814 bytes_processed =
815 BIO_read(socket_side_, buffers_[kWriteEncrypted] + start, length);
816 if (bytes_processed < 0) {
817 if (SSL_LOG_DATA) {
818 Syslog::Print("WriteEncrypted BIO_read returned error %d\n",
819 bytes_processed);
820 }
821 return 0;
822 } else {
823 if (SSL_LOG_DATA) {
824 Syslog::Print("WriteEncrypted BIO_read wrote %d bytes\n",
825 bytes_processed);
826 }
827 }
828 }
829 return bytes_processed;
830}
831
832} // namespace bin
833} // namespace dart
834
835#endif // !defined(DART_IO_SECURE_SOCKET_DISABLED)
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
#define UNREACHABLE()
Definition: assert.h:248
#define FUNCTION_NAME(name)
Definition: builtin.h:19
char * buffer() const
Definition: text_buffer.h:35
static void Print(const char *format,...) PRINTF_ATTRIBUTE(1
static char * StrDup(const char *s)
bool Value() const
Definition: dartutils.h:465
int32_t Value() const
Definition: dartutils.h:475
static Dart_CObject * NewString(const char *str)
Definition: dartutils.cc:927
static Dart_CObject * NewArray(intptr_t length)
Definition: dartutils.cc:936
static Dart_CObject * NewInt32(int32_t value)
Definition: dartutils.cc:902
static bool GetBooleanValue(Dart_Handle bool_obj)
Definition: dartutils.cc:137
static intptr_t GetNativeIntptrArgument(Dart_NativeArguments args, intptr_t index)
Definition: dartutils.cc:166
static Dart_Handle NewString(const char *str)
Definition: dartutils.h:214
static Dart_Handle NewDartArgumentError(const char *message)
Definition: dartutils.cc:746
static Dart_Handle NewInternalError(const char *message)
Definition: dartutils.cc:781
static bool GetNativeBooleanArgument(Dart_NativeArguments args, intptr_t index)
Definition: dartutils.cc:146
void RegisterCallbacks(SSL *ssl)
SSL_CTX * context() const
bool allow_tls_renegotiation() const
TrustEvaluateHandlerFunc GetTrustEvaluateHandler() const
static void SetAlpnProtocolList(Dart_Handle protocols_handle, SSL *ssl, SSLCertContext *context, bool is_server)
static constexpr int kSecurityContextNativeFieldIndex
void Connect(const char *hostname, SSLCertContext *context, bool is_server, bool request_client_certificate, bool require_client_certificate, Dart_Handle protocols_handle)
int ProcessReadEncryptedBuffer(int start, int end)
void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete)
void RegisterKeyLogPort(Dart_Port key_log_port)
int ProcessWritePlaintextBuffer(int start, int end)
void MarkAsTrusted(Dart_NativeArguments args)
void RegisterBadCertificateCallback(Dart_Handle callback)
void GetSelectedProtocol(Dart_NativeArguments args)
bool ProcessAllBuffers(int starts[kNumBuffers], int ends[kNumBuffers], bool in_handshake)
static CObject * ProcessFilterRequest(const CObjectArray &request)
int Handshake(Dart_Port reply_port)
static const intptr_t kApproximateSize
static constexpr int kSSLFilterNativeFieldIndex
int ProcessReadPlaintextBuffer(int start, int end)
int ProcessWriteEncryptedBuffer(int start, int end)
Dart_Port reply_port() const
static constexpr int SSL_ERROR_MESSAGE_BUFFER_SIZE
static uint32_t FetchErrorString(const SSL *ssl, TextBuffer *text_buffer)
static void CheckStatusSSL(int status, const char *type, const char *message, const SSL *ssl)
static bool IsValidAddress(const char *address)
Definition: socket_base.cc:306
static Dart_Handle WrappedX509Certificate(X509 *certificate)
#define ILLEGAL_PORT
Definition: dart_api.h:1535
int64_t Dart_Port
Definition: dart_api.h:1525
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
@ Dart_TypedData_kUint8
Definition: dart_api.h:2615
#define ASSERT(E)
#define FATAL(error)
glong glong end
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
size_t length
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: SkSLString.cpp:83
const bool SSL_LOG_STATUS
static Dart_Handle ThrowIfError(Dart_Handle handle)
Definition: dartutils.h:31
void FUNCTION_NAME() SecureSocket_Connect(Dart_NativeArguments args)
void FUNCTION_NAME() SecureSocket_RegisterHandshakeCompleteCallback(Dart_NativeArguments args)
void FUNCTION_NAME() SecureSocket_PeerCertificate(Dart_NativeArguments args)
void FUNCTION_NAME() SecureSocket_Destroy(Dart_NativeArguments args)
static void DeleteFilter(void *isolate_data, void *filter_pointer)
Definition: filter.cc:259
void FUNCTION_NAME() SecureSocket_NewX509CertificateWrapper(Dart_NativeArguments args)
const bool SSL_LOG_DATA
void FUNCTION_NAME() SecureSocket_Init(Dart_NativeArguments args)
void FUNCTION_NAME() SecureSocket_RegisterKeyLogPort(Dart_NativeArguments args)
void(* TrustEvaluateHandlerFunc)(Dart_Port dest_port_id, Dart_CObject *message)
void FUNCTION_NAME() SecureSocket_FilterPointer(Dart_NativeArguments args)
void FUNCTION_NAME() SecureSocket_MarkAsTrusted(Dart_NativeArguments args)
static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter *filter)
void FUNCTION_NAME() SecureSocket_RegisterBadCertificateCallback(Dart_NativeArguments args)
void FUNCTION_NAME() SecureSocket_GetSelectedProtocol(Dart_NativeArguments args)
void FUNCTION_NAME() SecureSocket_Handshake(Dart_NativeArguments args)
static Dart_Handle GetFilter(Dart_Handle filter_obj, Filter **filter)
Definition: filter.cc:20
Definition: dart_vm.cc:33
constexpr intptr_t MB
Definition: globals.h:530
DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index)
DART_EXPORT bool Dart_IsInstance(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t *utf8_array, intptr_t length)
DART_EXPORT void Dart_PropagateError(Dart_Handle handle)
DART_EXPORT Dart_FinalizableHandle Dart_NewFinalizableHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
constexpr intptr_t KB
Definition: globals.h:528
DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, int index, intptr_t value)
DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type, void *data, intptr_t length)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance)
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id)
DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value)
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT Dart_Port Dart_NewNativePort(const char *name, Dart_NativeMessageHandler handler, bool handle_concurrently)
DART_EXPORT Dart_Handle Dart_Null()
static int8_t data[kExtLength]
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object, const char **cstr)
DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port, Dart_Port *port_id)
DART_EXPORT Dart_Handle Dart_HandleFromPersistent(Dart_PersistentHandle object)
DART_EXPORT bool Dart_IsClosure(Dart_Handle object)
DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer, int64_t *value)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service port
Definition: switches.h:87
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
#define RETURN_IF_ERROR(handle)