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

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

Issue 1845273004: Allows adding trusted certs on iOS. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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 | « no previous file | sdk/lib/io/security_context.dart » ('j') | sdk/lib/io/security_context.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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)
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/io/security_context.dart » ('j') | sdk/lib/io/security_context.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698