| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED) | 5 #if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if TARGET_OS_IOS | 8 #if TARGET_OS_IOS |
| 9 | 9 |
| 10 #include "bin/secure_socket.h" | 10 #include "bin/secure_socket.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 // Return the error from the containing function if handle is an error handle. | 37 // Return the error from the containing function if handle is an error handle. |
| 38 #define RETURN_IF_ERROR(handle) \ | 38 #define RETURN_IF_ERROR(handle) \ |
| 39 { \ | 39 { \ |
| 40 Dart_Handle __handle = handle; \ | 40 Dart_Handle __handle = handle; \ |
| 41 if (Dart_IsError((__handle))) { \ | 41 if (Dart_IsError((__handle))) { \ |
| 42 return __handle; \ | 42 return __handle; \ |
| 43 } \ | 43 } \ |
| 44 } | 44 } |
| 45 | 45 |
| 46 // We need to access this private API function to create a SecIdentityRef | |
| 47 // without writing a custom keychain to the filesystem. This is the approach | |
| 48 // taken in WebKit: | |
| 49 // https://webkit.googlesource.com/WebKit/+/master/Source/WebKit2/Shared/cf/Argu
mentCodersCF.cpp | |
| 50 extern "C" { | |
| 51 SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, | |
| 52 SecCertificateRef certificate, | |
| 53 SecKeyRef private_key); | |
| 54 } | |
| 55 | |
| 56 namespace dart { | 46 namespace dart { |
| 57 namespace bin { | 47 namespace bin { |
| 58 | 48 |
| 59 static const int kSSLFilterNativeFieldIndex = 0; | 49 static const int kSSLFilterNativeFieldIndex = 0; |
| 60 static const int kSecurityContextNativeFieldIndex = 0; | 50 static const int kSecurityContextNativeFieldIndex = 0; |
| 61 static const int kX509NativeFieldIndex = 0; | 51 static const int kX509NativeFieldIndex = 0; |
| 62 | 52 |
| 63 static const bool SSL_LOG_STATUS = false; | 53 static const bool SSL_LOG_STATUS = false; |
| 64 static const bool SSL_LOG_DATA = false; | 54 static const bool SSL_LOG_DATA = false; |
| 65 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; | 55 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; |
| 66 | 56 |
| 67 // SSLCertContext wraps the certificates needed for a SecureTransport | 57 // SSLCertContext wraps the certificates needed for a SecureTransport |
| 68 // connection. Fields are protected by the mutex_ field, and may only be set | 58 // connection. Fields are protected by the mutex_ field, and may only be set |
| 69 // once. This is to allow access by both the Dart thread and the IOService | 59 // once. This is to allow access by both the Dart thread and the IOService |
| 70 // thread. Setters return false if the field was already set. | 60 // thread. Setters return false if the field was already set. |
| 71 class SSLCertContext { | 61 class SSLCertContext { |
| 72 public: | 62 public: |
| 73 SSLCertContext() : | 63 SSLCertContext() : |
| 74 mutex_(new Mutex()), | 64 mutex_(new Mutex()), |
| 65 trusted_certs_(NULL), |
| 75 trust_builtin_(false) {} | 66 trust_builtin_(false) {} |
| 76 | 67 |
| 77 ~SSLCertContext() { | 68 ~SSLCertContext() { |
| 78 delete mutex_; | 69 delete mutex_; |
| 70 if (trusted_certs_ != NULL) { |
| 71 CFRelease(trusted_certs_); |
| 72 } |
| 73 } |
| 74 |
| 75 CFMutableArrayRef trusted_certs() { |
| 76 MutexLocker m(mutex_); |
| 77 return trusted_certs_; |
| 78 } |
| 79 void add_trusted_cert(SecCertificateRef trusted_cert) { |
| 80 // Takes ownership of trusted_cert. |
| 81 MutexLocker m(mutex_); |
| 82 if (trusted_certs_ == NULL) { |
| 83 trusted_certs_ = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
| 84 } |
| 85 CFArrayAppendValue(trusted_certs_, trusted_cert); |
| 86 CFRelease(trusted_cert); // trusted_cert is retained by the array. |
| 79 } | 87 } |
| 80 | 88 |
| 81 bool trust_builtin() { | 89 bool trust_builtin() { |
| 82 MutexLocker m(mutex_); | 90 MutexLocker m(mutex_); |
| 83 return trust_builtin_; | 91 return trust_builtin_; |
| 84 } | 92 } |
| 85 void set_trust_builtin(bool trust_builtin) { | 93 void set_trust_builtin(bool trust_builtin) { |
| 86 MutexLocker m(mutex_); | 94 MutexLocker m(mutex_); |
| 87 trust_builtin_ = trust_builtin; | 95 trust_builtin_ = trust_builtin; |
| 88 } | 96 } |
| 89 | 97 |
| 90 private: | 98 private: |
| 91 // The context is accessed both by Dart code and the IOService. This mutex | 99 // The context is accessed both by Dart code and the IOService. This mutex |
| 92 // protects all fields. | 100 // protects all fields. |
| 93 Mutex* mutex_; | 101 Mutex* mutex_; |
| 102 CFMutableArrayRef trusted_certs_; |
| 94 bool trust_builtin_; | 103 bool trust_builtin_; |
| 95 | 104 |
| 96 DISALLOW_COPY_AND_ASSIGN(SSLCertContext); | 105 DISALLOW_COPY_AND_ASSIGN(SSLCertContext); |
| 97 }; | 106 }; |
| 98 | 107 |
| 99 // Handle an error reported from the SecureTransport library. | 108 // Handle an error reported from the SecureTransport library. |
| 100 static void ThrowIOException(OSStatus status, | 109 static void ThrowIOException(OSStatus status, |
| 101 const char* exception_type, | 110 const char* exception_type, |
| 102 const char* message) { | 111 const char* message) { |
| 103 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); | 112 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 result, | 249 result, |
| 241 kX509NativeFieldIndex, | 250 kX509NativeFieldIndex, |
| 242 reinterpret_cast<intptr_t>(certificate)); | 251 reinterpret_cast<intptr_t>(certificate)); |
| 243 if (Dart_IsError(status)) { | 252 if (Dart_IsError(status)) { |
| 244 return status; | 253 return status; |
| 245 } | 254 } |
| 246 return result; | 255 return result; |
| 247 } | 256 } |
| 248 | 257 |
| 249 | 258 |
| 259 // Where the argument to the constructor is the handle for an object |
| 260 // implementing List<int>, this class creates a scope in which the memory |
| 261 // backing the list can be accessed. |
| 262 // |
| 263 // Do not make Dart_ API calls while in a ScopedMemBuffer. |
| 264 // Do not call Dart_PropagateError while in a ScopedMemBuffer. |
| 265 class ScopedMemBuffer { |
| 266 public: |
| 267 explicit ScopedMemBuffer(Dart_Handle object) { |
| 268 if (!Dart_IsTypedData(object) && !Dart_IsList(object)) { |
| 269 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 270 "Argument is not a List<int>")); |
| 271 } |
| 272 |
| 273 uint8_t* bytes = NULL; |
| 274 intptr_t bytes_len = 0; |
| 275 bool is_typed_data = false; |
| 276 if (Dart_IsTypedData(object)) { |
| 277 is_typed_data = true; |
| 278 Dart_TypedData_Type typ; |
| 279 ThrowIfError(Dart_TypedDataAcquireData( |
| 280 object, |
| 281 &typ, |
| 282 reinterpret_cast<void**>(&bytes), |
| 283 &bytes_len)); |
| 284 } else { |
| 285 ASSERT(Dart_IsList(object)); |
| 286 ThrowIfError(Dart_ListLength(object, &bytes_len)); |
| 287 bytes = Dart_ScopeAllocate(bytes_len); |
| 288 ASSERT(bytes != NULL); |
| 289 ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len)); |
| 290 } |
| 291 |
| 292 object_ = object; |
| 293 bytes_ = bytes; |
| 294 bytes_len_ = bytes_len; |
| 295 is_typed_data_ = is_typed_data; |
| 296 } |
| 297 |
| 298 ~ScopedMemBuffer() { |
| 299 if (is_typed_data_) { |
| 300 ThrowIfError(Dart_TypedDataReleaseData(object_)); |
| 301 } |
| 302 } |
| 303 |
| 304 uint8_t* get() const { return bytes_; } |
| 305 intptr_t length() const { return bytes_len_; } |
| 306 |
| 307 private: |
| 308 Dart_Handle object_; |
| 309 uint8_t* bytes_; |
| 310 intptr_t bytes_len_; |
| 311 bool is_typed_data_; |
| 312 |
| 313 DISALLOW_ALLOCATION(); |
| 314 DISALLOW_COPY_AND_ASSIGN(ScopedMemBuffer); |
| 315 }; |
| 316 |
| 317 |
| 250 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { | 318 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { |
| 251 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | 319 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 252 SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer. | 320 SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer. |
| 253 Dart_Handle err = SetFilter(args, filter); | 321 Dart_Handle err = SetFilter(args, filter); |
| 254 if (Dart_IsError(err)) { | 322 if (Dart_IsError(err)) { |
| 255 delete filter; | 323 delete filter; |
| 256 Dart_PropagateError(err); | 324 Dart_PropagateError(err); |
| 257 } | 325 } |
| 258 err = filter->Init(dart_this); | 326 err = filter->Init(dart_this); |
| 259 if (Dart_IsError(err)) { | 327 if (Dart_IsError(err)) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 | 449 |
| 382 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 450 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
| 383 Dart_NativeArguments args) { | 451 Dart_NativeArguments args) { |
| 384 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 452 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
| 385 "SecurityContext.usePrivateKeyBytes is not yet implemented.")); | 453 "SecurityContext.usePrivateKeyBytes is not yet implemented.")); |
| 386 } | 454 } |
| 387 | 455 |
| 388 | 456 |
| 389 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 457 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
| 390 Dart_NativeArguments args) { | 458 Dart_NativeArguments args) { |
| 391 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 459 SSLCertContext* context = GetSecurityContext(args); |
| 392 "SecurityContext.setTrustedCertificatesBytes is not yet implemented.")); | 460 |
| 461 OSStatus status = noErr; |
| 462 SecCertificateRef cert = NULL; |
| 463 { |
| 464 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 465 CFDataRef cfdata = CFDataCreateWithBytesNoCopy( |
| 466 NULL, buffer.get(), buffer.length(), kCFAllocatorNull); |
| 467 cert = SecCertificateCreateWithData(NULL, cfdata); |
| 468 CFRelease(cfdata); |
| 469 } |
| 470 |
| 471 // Add the certs to the context. |
| 472 if (cert != NULL) { |
| 473 context->add_trusted_cert(cert); |
| 474 } else { |
| 475 status = errSSLBadCert; |
| 476 } |
| 477 CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes"); |
| 393 } | 478 } |
| 394 | 479 |
| 395 | 480 |
| 396 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { | 481 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { |
| 397 Dart_SetReturnValue(args, Dart_NewBoolean(false)); | 482 Dart_SetReturnValue(args, Dart_NewBoolean(false)); |
| 398 } | 483 } |
| 399 | 484 |
| 400 | 485 |
| 401 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 486 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
| 402 Dart_NativeArguments args) { | 487 Dart_NativeArguments args) { |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 // A client certificate was requested, but not required, and wasn't sent. | 976 // A client certificate was requested, but not required, and wasn't sent. |
| 892 return noErr; | 977 return noErr; |
| 893 } | 978 } |
| 894 if (SSL_LOG_STATUS) { | 979 if (SSL_LOG_STATUS) { |
| 895 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", | 980 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", |
| 896 static_cast<intptr_t>(status)); | 981 static_cast<intptr_t>(status)); |
| 897 } | 982 } |
| 898 return status; | 983 return status; |
| 899 } | 984 } |
| 900 | 985 |
| 901 CFArrayRef trusted_certs = | 986 CFArrayRef trusted_certs = NULL; |
| 902 CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); | 987 if (cert_context_->trusted_certs() != NULL) { |
| 988 trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs()); |
| 989 } else { |
| 990 trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); |
| 991 } |
| 903 | 992 |
| 904 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); | 993 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); |
| 905 if (status != noErr) { | 994 if (status != noErr) { |
| 906 if (SSL_LOG_STATUS) { | 995 if (SSL_LOG_STATUS) { |
| 907 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", | 996 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", |
| 908 static_cast<intptr_t>(status)); | 997 static_cast<intptr_t>(status)); |
| 909 } | 998 } |
| 910 CFRelease(trusted_certs); | 999 CFRelease(trusted_certs); |
| 911 CFRelease(peer_trust); | 1000 CFRelease(peer_trust); |
| 912 return status; | 1001 return status; |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1301 *bytes_processed = static_cast<intptr_t>(bytes); | 1390 *bytes_processed = static_cast<intptr_t>(bytes); |
| 1302 return status; | 1391 return status; |
| 1303 } | 1392 } |
| 1304 | 1393 |
| 1305 } // namespace bin | 1394 } // namespace bin |
| 1306 } // namespace dart | 1395 } // namespace dart |
| 1307 | 1396 |
| 1308 #endif // TARGET_OS_IOS | 1397 #endif // TARGET_OS_IOS |
| 1309 | 1398 |
| 1310 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1399 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| OLD | NEW |