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 |