Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: runtime/bin/secure_socket_filter.cc

Issue 2903743002: Porting SecureSocket to use BoringSSL on OSX (Closed)
Patch Set: Addressed nits, confirmed change works on Windows Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/bin/secure_socket_filter.h ('k') | runtime/bin/secure_socket_ios.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
6
7 #include "bin/secure_socket_filter.h"
8
9 #include <openssl/bio.h>
10 #include <openssl/ssl.h>
11 #include <openssl/x509.h>
12
13 #include "bin/lockers.h"
14 #include "bin/log.h"
15 #include "bin/secure_socket_utils.h"
16 #include "bin/security_context.h"
17 #include "platform/text_buffer.h"
18
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
29 namespace dart {
30 namespace bin {
31
32 bool SSLFilter::library_initialized_ = false;
33 // To protect library initialization.
34 Mutex* SSLFilter::mutex_ = new Mutex();
35 int SSLFilter::filter_ssl_index;
36
37 const intptr_t SSLFilter::kInternalBIOSize = 10 * KB;
38 const intptr_t SSLFilter::kApproximateSize =
39 sizeof(SSLFilter) + (2 * SSLFilter::kInternalBIOSize);
40
41 static SSLFilter* GetFilter(Dart_NativeArguments args) {
42 SSLFilter* filter;
43 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
44 ASSERT(Dart_IsInstance(dart_this));
45 ThrowIfError(Dart_GetNativeInstanceField(
46 dart_this, SSLFilter::kSSLFilterNativeFieldIndex,
47 reinterpret_cast<intptr_t*>(&filter)));
48 return filter;
49 }
50
51
52 static void DeleteFilter(void* isolate_data,
53 Dart_WeakPersistentHandle handle,
54 void* context_pointer) {
55 SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
56 filter->Release();
57 }
58
59
60 static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
61 ASSERT(filter != NULL);
62 Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
63 RETURN_IF_ERROR(dart_this);
64 ASSERT(Dart_IsInstance(dart_this));
65 Dart_Handle err = Dart_SetNativeInstanceField(
66 dart_this, SSLFilter::kSSLFilterNativeFieldIndex,
67 reinterpret_cast<intptr_t>(filter));
68 RETURN_IF_ERROR(err);
69 Dart_NewWeakPersistentHandle(dart_this, reinterpret_cast<void*>(filter),
70 SSLFilter::kApproximateSize, DeleteFilter);
71 return Dart_Null();
72 }
73
74
75 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
76 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
77 SSLFilter* filter = new SSLFilter();
78 Dart_Handle err = SetFilter(args, filter);
79 if (Dart_IsError(err)) {
80 filter->Release();
81 Dart_PropagateError(err);
82 }
83 err = filter->Init(dart_this);
84 if (Dart_IsError(err)) {
85 // The finalizer was set up by SetFilter. It will delete `filter` if there
86 // is an error.
87 filter->Destroy();
88 Dart_PropagateError(err);
89 }
90 }
91
92
93 void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
94 Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
95 Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
96 bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
97 bool request_client_certificate =
98 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
99 bool require_client_certificate =
100 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
101 Dart_Handle protocols_handle = ThrowIfError(Dart_GetNativeArgument(args, 6));
102
103 const char* host_name = NULL;
104 // TODO(whesse): Is truncating a Dart string containing \0 what we want?
105 ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
106
107 SSLCertContext* context = NULL;
108 if (!Dart_IsNull(context_object)) {
109 ThrowIfError(Dart_GetNativeInstanceField(
110 context_object, SSLCertContext::kSecurityContextNativeFieldIndex,
111 reinterpret_cast<intptr_t*>(&context)));
112 }
113
114 // The protocols_handle is guaranteed to be a valid Uint8List.
115 // It will have the correct length encoding of the protocols array.
116 ASSERT(!Dart_IsNull(protocols_handle));
117 GetFilter(args)->Connect(host_name, context, is_server,
118 request_client_certificate,
119 require_client_certificate, protocols_handle);
120 }
121
122
123 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
124 SSLFilter* filter = GetFilter(args);
125 // There are two paths that can clean up an SSLFilter object. First,
126 // there is this explicit call to Destroy(), called from
127 // _SecureFilter.destroy() in Dart code. After a call to destroy(), the Dart
128 // code maintains the invariant that there will be no futher SSLFilter
129 // requests sent to the IO Service. Therefore, the internals of the SSLFilter
130 // are safe to deallocate, but not the SSLFilter itself, which is already
131 // set up to be cleaned up by the finalizer.
132 //
133 // The second path is through the finalizer, which we have to do in case
134 // some mishap prevents a call to _SecureFilter.destroy().
135 filter->Destroy();
136 }
137
138
139 void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
140 GetFilter(args)->Handshake();
141 }
142
143
144 void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
145 Dart_NativeArguments args) {
146 GetFilter(args)->GetSelectedProtocol(args);
147 }
148
149
150 void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
151 bool use_session_cache =
152 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
153 bool request_client_certificate =
154 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
155 bool require_client_certificate =
156 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
157 GetFilter(args)->Renegotiate(use_session_cache, request_client_certificate,
158 require_client_certificate);
159 }
160
161
162 void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
163 Dart_NativeArguments args) {
164 Dart_Handle handshake_complete =
165 ThrowIfError(Dart_GetNativeArgument(args, 1));
166 if (!Dart_IsClosure(handshake_complete)) {
167 Dart_ThrowException(DartUtils::NewDartArgumentError(
168 "Illegal argument to RegisterHandshakeCompleteCallback"));
169 }
170 GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
171 }
172
173
174 void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
175 Dart_NativeArguments args) {
176 Dart_Handle callback = ThrowIfError(Dart_GetNativeArgument(args, 1));
177 if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
178 Dart_ThrowException(DartUtils::NewDartArgumentError(
179 "Illegal argument to RegisterBadCertificateCallback"));
180 }
181 GetFilter(args)->RegisterBadCertificateCallback(callback);
182 }
183
184
185 void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) {
186 Dart_Handle cert = ThrowIfError(GetFilter(args)->PeerCertificate());
187 Dart_SetReturnValue(args, cert);
188 }
189
190
191 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
192 SSLFilter* filter = GetFilter(args);
193 // This filter pointer is passed to the IO Service thread. The IO Service
194 // thread must Release() the pointer when it is done with it.
195 filter->Retain();
196 intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
197 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
198 }
199
200
201 /**
202 * Pushes data through the SSL filter, reading and writing from circular
203 * buffers shared with Dart.
204 *
205 * The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
206 * pass encrypted and plaintext data to and from the C++ SSLFilter object.
207 *
208 * ProcessFilter is called with a CObject array containing the pointer to
209 * the SSLFilter, encoded as an int, and the start and end positions of the
210 * valid data in the four circular buffers. The function only reads from
211 * the valid data area of the input buffers, and only writes to the free
212 * area of the output buffers. The function returns the new start and end
213 * positions in the buffers, but it only updates start for input buffers, and
214 * end for output buffers. Therefore, the Dart thread can simultaneously
215 * write to the free space and end pointer of input buffers, and read from
216 * the data space of output buffers, and modify the start pointer.
217 *
218 * When ProcessFilter returns, the Dart thread is responsible for combining
219 * the updated pointers from Dart and C++, to make the new valid state of
220 * the circular buffer.
221 */
222 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
223 CObjectIntptr filter_object(request[0]);
224 SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
225 RefCntReleaseScope<SSLFilter> rs(filter);
226
227 bool in_handshake = CObjectBool(request[1]).Value();
228 int starts[SSLFilter::kNumBuffers];
229 int ends[SSLFilter::kNumBuffers];
230 for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
231 starts[i] = CObjectInt32(request[2 * i + 2]).Value();
232 ends[i] = CObjectInt32(request[2 * i + 3]).Value();
233 }
234
235 if (filter->ProcessAllBuffers(starts, ends, in_handshake)) {
236 CObjectArray* result =
237 new CObjectArray(CObject::NewArray(SSLFilter::kNumBuffers * 2));
238 for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
239 result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
240 result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
241 }
242 return result;
243 } else {
244 int32_t error_code = static_cast<int32_t>(ERR_peek_error());
245 TextBuffer error_string(SecureSocketUtils::SSL_ERROR_MESSAGE_BUFFER_SIZE);
246 SecureSocketUtils::FetchErrorString(filter->ssl_, &error_string);
247 CObjectArray* result = new CObjectArray(CObject::NewArray(2));
248 result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code)));
249 result->SetAt(1, new CObjectString(CObject::NewString(error_string.buf())));
250 return result;
251 }
252 }
253
254
255 bool SSLFilter::ProcessAllBuffers(int starts[kNumBuffers],
256 int ends[kNumBuffers],
257 bool in_handshake) {
258 for (int i = 0; i < kNumBuffers; ++i) {
259 if (in_handshake && (i == kReadPlaintext || i == kWritePlaintext)) continue;
260 int start = starts[i];
261 int end = ends[i];
262 int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
263 if (start < 0 || end < 0 || start >= size || end >= size) {
264 FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
265 }
266 switch (i) {
267 case kReadPlaintext:
268 case kWriteEncrypted:
269 // Write data to the circular buffer's free space. If the buffer
270 // is full, neither if statement is executed and nothing happens.
271 if (start <= end) {
272 // If the free space may be split into two segments,
273 // then the first is [end, size), unless start == 0.
274 // Then, since the last free byte is at position start - 2,
275 // the interval is [end, size - 1).
276 int buffer_end = (start == 0) ? size - 1 : size;
277 int bytes = (i == kReadPlaintext)
278 ? ProcessReadPlaintextBuffer(end, buffer_end)
279 : ProcessWriteEncryptedBuffer(end, buffer_end);
280 if (bytes < 0) return false;
281 end += bytes;
282 ASSERT(end <= size);
283 if (end == size) end = 0;
284 }
285 if (start > end + 1) {
286 int bytes = (i == kReadPlaintext)
287 ? ProcessReadPlaintextBuffer(end, start - 1)
288 : ProcessWriteEncryptedBuffer(end, start - 1);
289 if (bytes < 0) return false;
290 end += bytes;
291 ASSERT(end < start);
292 }
293 ends[i] = end;
294 break;
295 case kReadEncrypted:
296 case kWritePlaintext:
297 // Read/Write data from circular buffer. If the buffer is empty,
298 // neither if statement's condition is true.
299 if (end < start) {
300 // Data may be split into two segments. In this case,
301 // the first is [start, size).
302 int bytes = (i == kReadEncrypted)
303 ? ProcessReadEncryptedBuffer(start, size)
304 : ProcessWritePlaintextBuffer(start, size);
305 if (bytes < 0) return false;
306 start += bytes;
307 ASSERT(start <= size);
308 if (start == size) start = 0;
309 }
310 if (start < end) {
311 int bytes = (i == kReadEncrypted)
312 ? ProcessReadEncryptedBuffer(start, end)
313 : ProcessWritePlaintextBuffer(start, end);
314 if (bytes < 0) return false;
315 start += bytes;
316 ASSERT(start <= end);
317 }
318 starts[i] = start;
319 break;
320 default:
321 UNREACHABLE();
322 }
323 }
324 return true;
325 }
326
327
328 Dart_Handle SSLFilter::Init(Dart_Handle dart_this) {
329 if (!library_initialized_) {
330 InitializeLibrary();
331 }
332 ASSERT(string_start_ == NULL);
333 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
334 ASSERT(string_start_ != NULL);
335 ASSERT(string_length_ == NULL);
336 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
337 ASSERT(string_length_ != NULL);
338 ASSERT(bad_certificate_callback_ == NULL);
339 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
340 ASSERT(bad_certificate_callback_ != NULL);
341 // Caller handles cleanup on an error.
342 return InitializeBuffers(dart_this);
343 }
344
345
346 Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
347 // Create SSLFilter buffers as ExternalUint8Array objects.
348 Dart_Handle buffers_string = DartUtils::NewString("buffers");
349 RETURN_IF_ERROR(buffers_string);
350 Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
351 RETURN_IF_ERROR(dart_buffers_object);
352 Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
353 RETURN_IF_ERROR(secure_filter_impl_type);
354 Dart_Handle size_string = DartUtils::NewString("SIZE");
355 RETURN_IF_ERROR(size_string);
356 Dart_Handle dart_buffer_size =
357 Dart_GetField(secure_filter_impl_type, size_string);
358 RETURN_IF_ERROR(dart_buffer_size);
359
360 int64_t buffer_size = 0;
361 Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
362 RETURN_IF_ERROR(err);
363
364 Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
365 RETURN_IF_ERROR(encrypted_size_string);
366
367 Dart_Handle dart_encrypted_buffer_size =
368 Dart_GetField(secure_filter_impl_type, encrypted_size_string);
369 RETURN_IF_ERROR(dart_encrypted_buffer_size);
370
371 int64_t encrypted_buffer_size = 0;
372 err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
373 RETURN_IF_ERROR(err);
374
375 if (buffer_size <= 0 || buffer_size > 1 * MB) {
376 FATAL("Invalid buffer size in _ExternalBuffer");
377 }
378 if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
379 FATAL("Invalid encrypted buffer size in _ExternalBuffer");
380 }
381 buffer_size_ = static_cast<int>(buffer_size);
382 encrypted_buffer_size_ = static_cast<int>(encrypted_buffer_size);
383
384 Dart_Handle data_identifier = DartUtils::NewString("data");
385 RETURN_IF_ERROR(data_identifier);
386
387 for (int i = 0; i < kNumBuffers; i++) {
388 int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
389 buffers_[i] = new uint8_t[size];
390 ASSERT(buffers_[i] != NULL);
391 dart_buffer_objects_[i] = NULL;
392 }
393
394 Dart_Handle result = Dart_Null();
395 for (int i = 0; i < kNumBuffers; ++i) {
396 int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
397 result = Dart_ListGetAt(dart_buffers_object, i);
398 if (Dart_IsError(result)) {
399 break;
400 }
401
402 dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
403 ASSERT(dart_buffer_objects_[i] != NULL);
404 Dart_Handle data =
405 Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size);
406 if (Dart_IsError(data)) {
407 result = data;
408 break;
409 }
410 result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
411 if (Dart_IsError(result)) {
412 break;
413 }
414 result = Dart_SetField(result, data_identifier, data);
415 if (Dart_IsError(result)) {
416 break;
417 }
418 }
419
420 // Caller handles cleanup on an error.
421 return result;
422 }
423
424
425 void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
426 ASSERT(NULL == handshake_complete_);
427 handshake_complete_ = Dart_NewPersistentHandle(complete);
428
429 ASSERT(handshake_complete_ != NULL);
430 }
431
432
433 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
434 ASSERT(bad_certificate_callback_ != NULL);
435 Dart_DeletePersistentHandle(bad_certificate_callback_);
436 bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
437 ASSERT(bad_certificate_callback_ != NULL);
438 }
439
440
441 Dart_Handle SSLFilter::PeerCertificate() {
442 X509* ca = SSL_get_peer_certificate(ssl_);
443 if (ca == NULL) {
444 return Dart_Null();
445 }
446 return X509Helper::WrappedX509Certificate(ca);
447 }
448
449
450 void SSLFilter::InitializeLibrary() {
451 MutexLocker locker(mutex_);
452 if (!library_initialized_) {
453 SSL_library_init();
454 filter_ssl_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
455 ASSERT(filter_ssl_index >= 0);
456 library_initialized_ = true;
457 }
458 }
459
460
461 void SSLFilter::Connect(const char* hostname,
462 SSLCertContext* context,
463 bool is_server,
464 bool request_client_certificate,
465 bool require_client_certificate,
466 Dart_Handle protocols_handle) {
467 is_server_ = is_server;
468 if (in_handshake_) {
469 FATAL("Connect called twice on the same _SecureFilter.");
470 }
471
472 int status;
473 int error;
474 BIO* ssl_side;
475 status = BIO_new_bio_pair(&ssl_side, kInternalBIOSize, &socket_side_,
476 kInternalBIOSize);
477 SecureSocketUtils::CheckStatusSSL(status, "TlsException", "BIO_new_bio_pair",
478 ssl_);
479
480 ASSERT(context != NULL);
481 ASSERT(context->context() != NULL);
482 ssl_ = SSL_new(context->context());
483 SSL_set_bio(ssl_, ssl_side, ssl_side);
484 SSL_set_mode(ssl_, SSL_MODE_AUTO_RETRY); // TODO(whesse): Is this right?
485 SSL_set_ex_data(ssl_, filter_ssl_index, this);
486 context->RegisterCallbacks(ssl_);
487
488 if (is_server_) {
489 int certificate_mode =
490 request_client_certificate ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
491 if (require_client_certificate) {
492 certificate_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
493 }
494 SSL_set_verify(ssl_, certificate_mode, NULL);
495 } else {
496 SSLCertContext::SetAlpnProtocolList(protocols_handle, ssl_, NULL, false);
497 status = SSL_set_tlsext_host_name(ssl_, hostname);
498 SecureSocketUtils::CheckStatusSSL(status, "TlsException",
499 "Set SNI host name", ssl_);
500 // Sets the hostname in the certificate-checking object, so it is checked
501 // against the certificate presented by the server.
502 X509_VERIFY_PARAM* certificate_checking_parameters = SSL_get0_param(ssl_);
503 hostname_ = strdup(hostname);
504 X509_VERIFY_PARAM_set_flags(
505 certificate_checking_parameters,
506 X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_TRUSTED_FIRST);
507 X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0);
508 status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters,
509 hostname_, strlen(hostname_));
510 SecureSocketUtils::CheckStatusSSL(
511 status, "TlsException", "Set hostname for certificate checking", ssl_);
512 }
513 // Make the connection:
514 if (is_server_) {
515 status = SSL_accept(ssl_);
516 if (SSL_LOG_STATUS) {
517 Log::Print("SSL_accept status: %d\n", status);
518 }
519 if (status != 1) {
520 // TODO(whesse): expect a needs-data error here. Handle other errors.
521 error = SSL_get_error(ssl_, status);
522 if (SSL_LOG_STATUS) {
523 Log::Print("SSL_accept error: %d\n", error);
524 }
525 }
526 } else {
527 status = SSL_connect(ssl_);
528 if (SSL_LOG_STATUS) {
529 Log::Print("SSL_connect status: %d\n", status);
530 }
531 if (status != 1) {
532 // TODO(whesse): expect a needs-data error here. Handle other errors.
533 error = SSL_get_error(ssl_, status);
534 if (SSL_LOG_STATUS) {
535 Log::Print("SSL_connect error: %d\n", error);
536 }
537 }
538 }
539 Handshake();
540 }
541
542
543 void SSLFilter::Handshake() {
544 // Try and push handshake along.
545 int status;
546 status = SSL_do_handshake(ssl_);
547 if (callback_error != NULL) {
548 // The SSL_do_handshake will try performing a handshake and might call
549 // a CertificateCallback. If the certificate validation
550 // failed the 'callback_error" will be set by the certificateCallback
551 // logic and we propagate the error"
552 Dart_PropagateError(callback_error);
553 }
554 if (SSL_want_write(ssl_) || SSL_want_read(ssl_)) {
555 in_handshake_ = true;
556 return;
557 }
558 SecureSocketUtils::CheckStatusSSL(
559 status, "HandshakeException",
560 is_server_ ? "Handshake error in server" : "Handshake error in client",
561 ssl_);
562 // Handshake succeeded.
563 if (in_handshake_) {
564 // TODO(24071): Check return value of SSL_get_verify_result, this
565 // should give us the hostname check.
566 int result = SSL_get_verify_result(ssl_);
567 if (SSL_LOG_STATUS) {
568 Log::Print("Handshake verification status: %d\n", result);
569 X509* peer_certificate = SSL_get_peer_certificate(ssl_);
570 if (peer_certificate == NULL) {
571 Log::Print("No peer certificate received\n");
572 } else {
573 X509_NAME* s_name = X509_get_subject_name(peer_certificate);
574 printf("Peer certificate SN: ");
575 X509_NAME_print_ex_fp(stdout, s_name, 4, 0);
576 printf("\n");
577 }
578 }
579 ThrowIfError(Dart_InvokeClosure(
580 Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
581 in_handshake_ = false;
582 }
583 }
584
585
586 void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) {
587 const uint8_t* protocol;
588 unsigned length;
589 SSL_get0_alpn_selected(ssl_, &protocol, &length);
590 if (length == 0) {
591 Dart_SetReturnValue(args, Dart_Null());
592 } else {
593 Dart_SetReturnValue(args, Dart_NewStringFromUTF8(protocol, length));
594 }
595 }
596
597
598 void SSLFilter::Renegotiate(bool use_session_cache,
599 bool request_client_certificate,
600 bool require_client_certificate) {
601 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
602 // SSL_REQUEST_CERTIFICATE option is also set, so set it.
603 request_client_certificate =
604 request_client_certificate || require_client_certificate;
605 // TODO(24070, 24069): Implement setting the client certificate parameters,
606 // and triggering rehandshake.
607 }
608
609
610 void SSLFilter::FreeResources() {
611 if (ssl_ != NULL) {
612 SSL_free(ssl_);
613 ssl_ = NULL;
614 }
615 if (socket_side_ != NULL) {
616 BIO_free(socket_side_);
617 socket_side_ = NULL;
618 }
619 if (hostname_ != NULL) {
620 free(hostname_);
621 hostname_ = NULL;
622 }
623 for (int i = 0; i < kNumBuffers; ++i) {
624 if (buffers_[i] != NULL) {
625 delete[] buffers_[i];
626 buffers_[i] = NULL;
627 }
628 }
629 }
630
631
632 SSLFilter::~SSLFilter() {
633 FreeResources();
634 }
635
636
637 void SSLFilter::Destroy() {
638 for (int i = 0; i < kNumBuffers; ++i) {
639 if (dart_buffer_objects_[i] != NULL) {
640 Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
641 dart_buffer_objects_[i] = NULL;
642 }
643 }
644 if (string_start_ != NULL) {
645 Dart_DeletePersistentHandle(string_start_);
646 string_start_ = NULL;
647 }
648 if (string_length_ != NULL) {
649 Dart_DeletePersistentHandle(string_length_);
650 string_length_ = NULL;
651 }
652 if (handshake_complete_ != NULL) {
653 Dart_DeletePersistentHandle(handshake_complete_);
654 handshake_complete_ = NULL;
655 }
656 if (bad_certificate_callback_ != NULL) {
657 Dart_DeletePersistentHandle(bad_certificate_callback_);
658 bad_certificate_callback_ = NULL;
659 }
660 FreeResources();
661 }
662
663
664 /* Read decrypted data from the filter to the circular buffer */
665 int SSLFilter::ProcessReadPlaintextBuffer(int start, int end) {
666 int length = end - start;
667 int bytes_processed = 0;
668 if (length > 0) {
669 bytes_processed = SSL_read(
670 ssl_, reinterpret_cast<char*>((buffers_[kReadPlaintext] + start)),
671 length);
672 if (bytes_processed < 0) {
673 int error = SSL_get_error(ssl_, bytes_processed);
674 USE(error);
675 bytes_processed = 0;
676 }
677 }
678 return bytes_processed;
679 }
680
681
682 int SSLFilter::ProcessWritePlaintextBuffer(int start, int end) {
683 int length = end - start;
684 int bytes_processed =
685 SSL_write(ssl_, buffers_[kWritePlaintext] + start, length);
686 if (bytes_processed < 0) {
687 if (SSL_LOG_DATA) {
688 Log::Print("SSL_write returned error %d\n", bytes_processed);
689 }
690 return 0;
691 }
692 return bytes_processed;
693 }
694
695
696 /* Read encrypted data from the circular buffer to the filter */
697 int SSLFilter::ProcessReadEncryptedBuffer(int start, int end) {
698 int length = end - start;
699 if (SSL_LOG_DATA)
700 Log::Print("Entering ProcessReadEncryptedBuffer with %d bytes\n", length);
701 int bytes_processed = 0;
702 if (length > 0) {
703 bytes_processed =
704 BIO_write(socket_side_, buffers_[kReadEncrypted] + start, length);
705 if (bytes_processed <= 0) {
706 bool retry = BIO_should_retry(socket_side_);
707 if (!retry) {
708 if (SSL_LOG_DATA)
709 Log::Print("BIO_write failed in ReadEncryptedBuffer\n");
710 }
711 bytes_processed = 0;
712 }
713 }
714 if (SSL_LOG_DATA)
715 Log::Print("Leaving ProcessReadEncryptedBuffer wrote %d bytes\n",
716 bytes_processed);
717 return bytes_processed;
718 }
719
720
721 int SSLFilter::ProcessWriteEncryptedBuffer(int start, int end) {
722 int length = end - start;
723 int bytes_processed = 0;
724 if (length > 0) {
725 bytes_processed =
726 BIO_read(socket_side_, buffers_[kWriteEncrypted] + start, length);
727 if (bytes_processed < 0) {
728 if (SSL_LOG_DATA)
729 Log::Print("WriteEncrypted BIO_read returned error %d\n",
730 bytes_processed);
731 return 0;
732 } else {
733 if (SSL_LOG_DATA)
734 Log::Print("WriteEncrypted BIO_read wrote %d bytes\n",
735 bytes_processed);
736 }
737 }
738 return bytes_processed;
739 }
740
741 } // namespace bin
742 } // namespace dart
743
744 #endif // !defined(DART_IO_DISABLED) &&
745 // !defined(DART_IO_SECURE_SOCKET_DISABLED)
OLDNEW
« no previous file with comments | « runtime/bin/secure_socket_filter.h ('k') | runtime/bin/secure_socket_ios.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698