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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 | 390 |
382 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 391 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
383 Dart_NativeArguments args) { | 392 Dart_NativeArguments args) { |
384 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 393 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
385 "SecurityContext.usePrivateKeyBytes is not yet implemented.")); | 394 "SecurityContext.usePrivateKeyBytes is not yet implemented.")); |
386 } | 395 } |
387 | 396 |
388 | 397 |
389 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 398 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
390 Dart_NativeArguments args) { | 399 Dart_NativeArguments args) { |
391 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 400 SSLCertContext* context = GetSecurityContext(args); |
392 "SecurityContext.setTrustedCertificatesBytes is not yet implemented.")); | 401 |
| 402 OSStatus status = noErr; |
| 403 SecCertificateRef cert = NULL; |
| 404 { |
| 405 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 406 CFDataRef cfdata = CFDataCreateWithBytesNoCopy( |
| 407 NULL, buffer.get(), buffer.length(), kCFAllocatorNull); |
| 408 cert = SecCertificateCreateWithData(NULL, cfdata); |
| 409 CFRelease(cfdata); |
| 410 } |
| 411 |
| 412 // Add the certs to the context. |
| 413 if (cert != NULL) { |
| 414 context->add_trusted_cert(cert); |
| 415 } else { |
| 416 status = errSSLBadCert; |
| 417 } |
| 418 CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes"); |
393 } | 419 } |
394 | 420 |
395 | 421 |
396 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { | 422 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { |
397 Dart_SetReturnValue(args, Dart_NewBoolean(false)); | 423 Dart_SetReturnValue(args, Dart_NewBoolean(false)); |
398 } | 424 } |
399 | 425 |
400 | 426 |
401 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 427 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
402 Dart_NativeArguments args) { | 428 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. | 917 // A client certificate was requested, but not required, and wasn't sent. |
892 return noErr; | 918 return noErr; |
893 } | 919 } |
894 if (SSL_LOG_STATUS) { | 920 if (SSL_LOG_STATUS) { |
895 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", | 921 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", |
896 static_cast<intptr_t>(status)); | 922 static_cast<intptr_t>(status)); |
897 } | 923 } |
898 return status; | 924 return status; |
899 } | 925 } |
900 | 926 |
901 CFArrayRef trusted_certs = | 927 CFArrayRef trusted_certs = NULL; |
902 CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); | 928 if (cert_context_->trusted_certs() != NULL) { |
| 929 trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs()); |
| 930 } else { |
| 931 trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); |
| 932 } |
903 | 933 |
904 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); | 934 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); |
905 if (status != noErr) { | 935 if (status != noErr) { |
906 if (SSL_LOG_STATUS) { | 936 if (SSL_LOG_STATUS) { |
907 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", | 937 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", |
908 static_cast<intptr_t>(status)); | 938 static_cast<intptr_t>(status)); |
909 } | 939 } |
910 CFRelease(trusted_certs); | 940 CFRelease(trusted_certs); |
911 CFRelease(peer_trust); | 941 CFRelease(peer_trust); |
912 return status; | 942 return status; |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1301 *bytes_processed = static_cast<intptr_t>(bytes); | 1331 *bytes_processed = static_cast<intptr_t>(bytes); |
1302 return status; | 1332 return status; |
1303 } | 1333 } |
1304 | 1334 |
1305 } // namespace bin | 1335 } // namespace bin |
1306 } // namespace dart | 1336 } // namespace dart |
1307 | 1337 |
1308 #endif // TARGET_OS_IOS | 1338 #endif // TARGET_OS_IOS |
1309 | 1339 |
1310 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1340 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
OLD | NEW |