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 defined(TARGET_OS_MACOS) | 8 #if TARGET_OS_IOS |
9 | 9 |
10 #include "bin/secure_socket.h" | 10 #include "bin/secure_socket.h" |
11 #include "bin/secure_socket_macos.h" | 11 #include "bin/secure_socket_macos.h" |
12 | 12 |
13 #include <errno.h> | 13 #include <errno.h> |
14 #include <fcntl.h> | 14 #include <fcntl.h> |
15 #include <sys/stat.h> | 15 #include <sys/stat.h> |
16 #include <sys/syslimits.h> | 16 #include <sys/syslimits.h> |
17 #include <stdio.h> | 17 #include <stdio.h> |
18 #include <string.h> | 18 #include <string.h> |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 | 55 |
56 namespace dart { | 56 namespace dart { |
57 namespace bin { | 57 namespace bin { |
58 | 58 |
59 static const int kSSLFilterNativeFieldIndex = 0; | 59 static const int kSSLFilterNativeFieldIndex = 0; |
60 static const int kSecurityContextNativeFieldIndex = 0; | 60 static const int kSecurityContextNativeFieldIndex = 0; |
61 static const int kX509NativeFieldIndex = 0; | 61 static const int kX509NativeFieldIndex = 0; |
62 | 62 |
63 static const bool SSL_LOG_STATUS = false; | 63 static const bool SSL_LOG_STATUS = false; |
64 static const bool SSL_LOG_DATA = false; | 64 static const bool SSL_LOG_DATA = false; |
65 static const bool SSL_LOG_CERTS = false; | |
66 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; | 65 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; |
67 static const intptr_t PEM_BUFSIZE = 1024; | |
68 | 66 |
69 // SSLCertContext wraps the certificates needed for a SecureTransport | 67 // SSLCertContext wraps the certificates needed for a SecureTransport |
70 // connection. Fields are protected by the mutex_ field, and may only be set | 68 // connection. Fields are protected by the mutex_ field, and may only be set |
71 // once. This is to allow access by both the Dart thread and the IOService | 69 // once. This is to allow access by both the Dart thread and the IOService |
72 // thread. Setters return false if the field was already set. | 70 // thread. Setters return false if the field was already set. |
73 class SSLCertContext { | 71 class SSLCertContext { |
74 public: | 72 public: |
75 SSLCertContext() : | 73 SSLCertContext() : |
76 mutex_(new Mutex()), | 74 mutex_(new Mutex()), |
77 private_key_(NULL), | |
78 keychain_(NULL), | |
79 cert_chain_(NULL), | |
80 trusted_certs_(NULL), | |
81 cert_authorities_(NULL), | |
82 trust_builtin_(false) {} | 75 trust_builtin_(false) {} |
83 | 76 |
84 ~SSLCertContext() { | 77 ~SSLCertContext() { |
85 if (private_key_ != NULL) { | |
86 CFRelease(private_key_); | |
87 } | |
88 if (keychain_ != NULL) { | |
89 SecKeychainDelete(keychain_); | |
90 CFRelease(keychain_); | |
91 } | |
92 if (cert_chain_ != NULL) { | |
93 CFRelease(cert_chain_); | |
94 } | |
95 if (trusted_certs_ != NULL) { | |
96 CFRelease(trusted_certs_); | |
97 } | |
98 if (cert_authorities_ != NULL) { | |
99 CFRelease(cert_authorities_); | |
100 } | |
101 delete mutex_; | 78 delete mutex_; |
102 } | 79 } |
103 | 80 |
104 SecKeyRef private_key() { | |
105 MutexLocker m(mutex_); | |
106 return private_key_; | |
107 } | |
108 bool set_private_key(SecKeyRef private_key) { | |
109 MutexLocker m(mutex_); | |
110 if (private_key_ != NULL) { | |
111 return false; | |
112 } | |
113 private_key_ = private_key; | |
114 return true; | |
115 } | |
116 | |
117 SecKeychainRef keychain() { | |
118 MutexLocker m(mutex_); | |
119 return keychain_; | |
120 } | |
121 bool set_keychain(SecKeychainRef keychain) { | |
122 MutexLocker m(mutex_); | |
123 if (keychain_ != NULL) { | |
124 return false; | |
125 } | |
126 keychain_ = keychain; | |
127 return true; | |
128 } | |
129 | |
130 CFArrayRef cert_chain() { | |
131 MutexLocker m(mutex_); | |
132 return cert_chain_; | |
133 } | |
134 bool set_cert_chain(CFArrayRef cert_chain) { | |
135 MutexLocker m(mutex_); | |
136 if (cert_chain_ != NULL) { | |
137 return false; | |
138 } | |
139 cert_chain_ = cert_chain; | |
140 return true; | |
141 } | |
142 | |
143 CFArrayRef trusted_certs() { | |
144 MutexLocker m(mutex_); | |
145 return trusted_certs_; | |
146 } | |
147 bool set_trusted_certs(CFArrayRef trusted_certs) { | |
148 MutexLocker m(mutex_); | |
149 if (trusted_certs_ != NULL) { | |
150 return false; | |
151 } | |
152 trusted_certs_ = trusted_certs; | |
153 return true; | |
154 } | |
155 | |
156 CFArrayRef cert_authorities() { | |
157 MutexLocker m(mutex_); | |
158 return cert_authorities_; | |
159 } | |
160 bool set_cert_authorities(CFArrayRef cert_authorities) { | |
161 MutexLocker m(mutex_); | |
162 if (cert_authorities_ != NULL) { | |
163 return false; | |
164 } | |
165 cert_authorities_ = cert_authorities; | |
166 return true; | |
167 } | |
168 | |
169 bool trust_builtin() { | 81 bool trust_builtin() { |
170 MutexLocker m(mutex_); | 82 MutexLocker m(mutex_); |
171 return trust_builtin_; | 83 return trust_builtin_; |
172 } | 84 } |
173 void set_trust_builtin(bool trust_builtin) { | 85 void set_trust_builtin(bool trust_builtin) { |
174 MutexLocker m(mutex_); | 86 MutexLocker m(mutex_); |
175 trust_builtin_ = trust_builtin; | 87 trust_builtin_ = trust_builtin; |
176 } | 88 } |
177 | 89 |
178 private: | 90 private: |
179 // The context is accessed both by Dart code and the IOService. This mutex | 91 // The context is accessed both by Dart code and the IOService. This mutex |
180 // protects all fields. | 92 // protects all fields. |
181 Mutex* mutex_; | 93 Mutex* mutex_; |
182 | |
183 SecKeyRef private_key_; | |
184 SecKeychainRef keychain_; | |
185 | |
186 // CFArrays of SecCertificateRef. | |
187 CFArrayRef cert_chain_; | |
188 CFArrayRef trusted_certs_; | |
189 CFArrayRef cert_authorities_; | |
190 | |
191 bool trust_builtin_; | 94 bool trust_builtin_; |
192 | 95 |
193 DISALLOW_COPY_AND_ASSIGN(SSLCertContext); | 96 DISALLOW_COPY_AND_ASSIGN(SSLCertContext); |
194 }; | 97 }; |
195 | 98 |
196 | |
197 static char* CFStringRefToCString(CFStringRef cfstring) { | |
198 CFIndex len = CFStringGetLength(cfstring); | |
199 CFIndex max_len = | |
200 CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1; | |
201 char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(max_len)); | |
202 ASSERT(result != NULL); | |
203 bool success = | |
204 CFStringGetCString(cfstring, result, max_len, kCFStringEncodingUTF8); | |
205 return success ? result : NULL; | |
206 } | |
207 | |
208 | |
209 // Handle an error reported from the SecureTransport library. | 99 // Handle an error reported from the SecureTransport library. |
210 static void ThrowIOException(OSStatus status, | 100 static void ThrowIOException(OSStatus status, |
211 const char* exception_type, | 101 const char* exception_type, |
212 const char* message) { | 102 const char* message) { |
213 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); | 103 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); |
214 CFStringRef error_string = SecCopyErrorMessageString(status, NULL); | 104 status_message.Printf("OSStatus = %ld: https://www.osstatus.com", |
215 if (error_string == NULL) { | 105 static_cast<intptr_t>(status)); |
216 status_message.Printf("OSStatus = %ld: https://www.osstatus.com", | |
217 static_cast<intptr_t>(status)); | |
218 } else { | |
219 char* error = CFStringRefToCString(error_string); | |
220 status_message.Printf("OSStatus = %ld: %s", | |
221 static_cast<intptr_t>(status), error); | |
222 CFRelease(error_string); | |
223 } | |
224 OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL); | 106 OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL); |
225 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); | 107 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); |
226 Dart_Handle exception = | 108 Dart_Handle exception = |
227 DartUtils::NewDartIOException(exception_type, message, os_error); | 109 DartUtils::NewDartIOException(exception_type, message, os_error); |
228 ASSERT(!Dart_IsError(exception)); | 110 ASSERT(!Dart_IsError(exception)); |
229 Dart_ThrowException(exception); | 111 Dart_ThrowException(exception); |
230 UNREACHABLE(); | 112 UNREACHABLE(); |
231 } | 113 } |
232 | 114 |
233 | 115 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 reinterpret_cast<intptr_t>(context)); | 194 reinterpret_cast<intptr_t>(context)); |
313 RETURN_IF_ERROR(err); | 195 RETURN_IF_ERROR(err); |
314 Dart_NewWeakPersistentHandle(dart_this, | 196 Dart_NewWeakPersistentHandle(dart_this, |
315 context, | 197 context, |
316 approximate_size_of_context, | 198 approximate_size_of_context, |
317 DeleteCertContext); | 199 DeleteCertContext); |
318 return Dart_Null(); | 200 return Dart_Null(); |
319 } | 201 } |
320 | 202 |
321 | 203 |
322 static SecCertificateRef GetX509Certificate(Dart_NativeArguments args) { | |
323 SecCertificateRef certificate; | |
324 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | |
325 ASSERT(Dart_IsInstance(dart_this)); | |
326 ThrowIfError(Dart_GetNativeInstanceField( | |
327 dart_this, | |
328 kX509NativeFieldIndex, | |
329 reinterpret_cast<intptr_t*>(&certificate))); | |
330 return certificate; | |
331 } | |
332 | |
333 | |
334 static void ReleaseCertificate(void* isolate_data, | 204 static void ReleaseCertificate(void* isolate_data, |
335 Dart_WeakPersistentHandle handle, | 205 Dart_WeakPersistentHandle handle, |
336 void* context_pointer) { | 206 void* context_pointer) { |
337 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer); | 207 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer); |
338 CFRelease(cert); | 208 CFRelease(cert); |
339 } | 209 } |
340 | 210 |
341 | 211 |
342 static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) { | 212 static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) { |
343 const intptr_t approximate_size_of_certificate = 1500; | 213 const intptr_t approximate_size_of_certificate = 1500; |
(...skipping 26 matching lines...) Expand all Loading... |
370 result, | 240 result, |
371 kX509NativeFieldIndex, | 241 kX509NativeFieldIndex, |
372 reinterpret_cast<intptr_t>(certificate)); | 242 reinterpret_cast<intptr_t>(certificate)); |
373 if (Dart_IsError(status)) { | 243 if (Dart_IsError(status)) { |
374 return status; | 244 return status; |
375 } | 245 } |
376 return result; | 246 return result; |
377 } | 247 } |
378 | 248 |
379 | 249 |
380 // Where the argument to the constructor is the handle for an object | |
381 // implementing List<int>, this class creates a scope in which the memory | |
382 // backing the list can be accessed. | |
383 // | |
384 // Do not make Dart_ API calls while in a ScopedMemBuffer. | |
385 // Do not call Dart_PropagateError while in a ScopedMemBuffer. | |
386 class ScopedMemBuffer { | |
387 public: | |
388 explicit ScopedMemBuffer(Dart_Handle object) { | |
389 if (!Dart_IsTypedData(object) && !Dart_IsList(object)) { | |
390 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
391 "Argument is not a List<int>")); | |
392 } | |
393 | |
394 uint8_t* bytes = NULL; | |
395 intptr_t bytes_len = 0; | |
396 bool is_typed_data = false; | |
397 if (Dart_IsTypedData(object)) { | |
398 is_typed_data = true; | |
399 Dart_TypedData_Type typ; | |
400 ThrowIfError(Dart_TypedDataAcquireData( | |
401 object, | |
402 &typ, | |
403 reinterpret_cast<void**>(&bytes), | |
404 &bytes_len)); | |
405 } else { | |
406 ASSERT(Dart_IsList(object)); | |
407 ThrowIfError(Dart_ListLength(object, &bytes_len)); | |
408 bytes = Dart_ScopeAllocate(bytes_len); | |
409 ASSERT(bytes != NULL); | |
410 ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len)); | |
411 } | |
412 | |
413 object_ = object; | |
414 bytes_ = bytes; | |
415 bytes_len_ = bytes_len; | |
416 is_typed_data_ = is_typed_data; | |
417 } | |
418 | |
419 ~ScopedMemBuffer() { | |
420 if (is_typed_data_) { | |
421 ThrowIfError(Dart_TypedDataReleaseData(object_)); | |
422 } | |
423 } | |
424 | |
425 uint8_t* get() const { return bytes_; } | |
426 intptr_t length() const { return bytes_len_; } | |
427 | |
428 private: | |
429 Dart_Handle object_; | |
430 uint8_t* bytes_; | |
431 intptr_t bytes_len_; | |
432 bool is_typed_data_; | |
433 | |
434 DISALLOW_ALLOCATION(); | |
435 DISALLOW_COPY_AND_ASSIGN(ScopedMemBuffer); | |
436 }; | |
437 | |
438 | |
439 static const char* GetPasswordArgument(Dart_NativeArguments args, | |
440 intptr_t index) { | |
441 Dart_Handle password_object = | |
442 ThrowIfError(Dart_GetNativeArgument(args, index)); | |
443 const char* password = NULL; | |
444 if (Dart_IsString(password_object)) { | |
445 ThrowIfError(Dart_StringToCString(password_object, &password)); | |
446 if (strlen(password) > PEM_BUFSIZE - 1) { | |
447 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
448 "Password length is greater than 1023 bytes.")); | |
449 } | |
450 } else if (Dart_IsNull(password_object)) { | |
451 password = ""; | |
452 } else { | |
453 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
454 "Password is not a String or null")); | |
455 } | |
456 return password; | |
457 } | |
458 | |
459 | |
460 static OSStatus GetKeyAndCerts(CFArrayRef items, | |
461 CFIndex items_length, | |
462 CFArrayRef* out_certs, | |
463 SecKeyRef* out_key) { | |
464 OSStatus status = noErr; | |
465 | |
466 // Loop through the items, take only the first private key/identity, ignore | |
467 // any others, populate out_certs. | |
468 CFMutableArrayRef certs = | |
469 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |
470 SecKeyRef key = NULL; | |
471 | |
472 for (CFIndex i = 0; i < items_length; ++i) { | |
473 CFTypeRef item = | |
474 reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i)); | |
475 CFTypeID item_type = CFGetTypeID(item); | |
476 if (item_type == SecCertificateGetTypeID()) { | |
477 if (SSL_LOG_CERTS) { | |
478 Log::Print("\titem %ld: Certificate\n", i); | |
479 } | |
480 CFArrayAppendValue(certs, item); | |
481 } else if ((item_type == SecKeyGetTypeID()) && (key == NULL)) { | |
482 if (SSL_LOG_CERTS) { | |
483 Log::Print("\titem %ld: Key\n", i); | |
484 } | |
485 key = reinterpret_cast<SecKeyRef>(const_cast<void*>(item)); | |
486 CFRetain(key); | |
487 } else if ((item_type == SecIdentityGetTypeID()) && (key == NULL)) { | |
488 if (SSL_LOG_CERTS) { | |
489 Log::Print("\titem %ld: Identity\n", i); | |
490 } | |
491 SecIdentityRef identity = | |
492 reinterpret_cast<SecIdentityRef>(const_cast<void*>(item)); | |
493 SecCertificateRef cert = NULL; | |
494 | |
495 status = SecIdentityCopyPrivateKey(identity, &key); | |
496 if (status != noErr) { | |
497 CFRelease(certs); | |
498 return status; | |
499 } | |
500 | |
501 status = SecIdentityCopyCertificate(identity, &cert); | |
502 if (status != noErr) { | |
503 CFRelease(key); | |
504 CFRelease(certs); | |
505 return status; | |
506 } | |
507 CFArrayAppendValue(certs, cert); | |
508 CFRelease(cert); | |
509 } | |
510 // Other item types are ignored. | |
511 } | |
512 | |
513 if (out_key == NULL) { | |
514 if (key != NULL) { | |
515 CFRelease(key); | |
516 } | |
517 } else { | |
518 *out_key = key; | |
519 } | |
520 | |
521 if (out_certs == NULL) { | |
522 if (certs != NULL) { | |
523 CFRelease(certs); | |
524 } | |
525 } else { | |
526 *out_certs = certs; | |
527 } | |
528 return status; | |
529 } | |
530 | |
531 | |
532 static OSStatus TryPEMImport(CFDataRef cfdata, | |
533 CFStringRef password, | |
534 CFArrayRef* out_certs, | |
535 SecKeyRef* out_key) { | |
536 OSStatus status = noErr; | |
537 | |
538 SecExternalFormat format = kSecFormatPEMSequence; | |
539 SecExternalItemType sitem_type = kSecItemTypeAggregate; | |
540 | |
541 SecItemImportExportKeyParameters params; | |
542 memset(¶ms, 0, sizeof(params)); | |
543 params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; | |
544 params.flags = kSecKeyNoAccessControl; | |
545 params.passphrase = password; | |
546 | |
547 CFArrayRef items = NULL; | |
548 status = SecItemImport( | |
549 cfdata, NULL, &format, &sitem_type, 0, ¶ms, NULL, &items); | |
550 | |
551 if (status != noErr) { | |
552 if (SSL_LOG_CERTS) { | |
553 Log::Print("TrySecItemImport failed with: %ld, type = %d, format = %d\n", | |
554 static_cast<intptr_t>(status), sitem_type, format); | |
555 } | |
556 return status; | |
557 } | |
558 | |
559 CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items); | |
560 if (SSL_LOG_CERTS) { | |
561 Log::Print( | |
562 "TrySecItemImport succeeded, type = %d, format = %d, count = %ld\n", | |
563 sitem_type, format, items_length); | |
564 } | |
565 | |
566 // Empty list indicates a decoding failure of some sort. | |
567 if ((items != NULL) && (items_length == 0)) { | |
568 CFRelease(items); | |
569 return errSSLBadCert; | |
570 } | |
571 | |
572 status = GetKeyAndCerts(items, items_length, out_certs, out_key); | |
573 CFRelease(items); | |
574 return status; | |
575 } | |
576 | |
577 | |
578 static char* TempKeychainPath() { | |
579 const char* exes = "keychaindir.XXXX"; | |
580 const char* fname = "keychain"; | |
581 const char* temp_dir = getenv("TMPDIR"); | |
582 if (temp_dir == NULL) { | |
583 temp_dir = getenv("TMP"); | |
584 } | |
585 if (temp_dir == NULL) { | |
586 temp_dir = "/tmp/"; | |
587 } | |
588 ASSERT(temp_dir != NULL); | |
589 | |
590 TextBuffer path(PATH_MAX); | |
591 path.Printf("%s/%s", temp_dir, exes); | |
592 char* ret = mkdtemp(path.buf()); | |
593 ASSERT(ret != NULL); | |
594 path.Printf("/%s", fname); | |
595 | |
596 char* result = | |
597 reinterpret_cast<char*>(Dart_ScopeAllocate(path.length() + 1)); | |
598 return strncpy(result, path.buf(), path.length() + 1); | |
599 } | |
600 | |
601 | |
602 static OSStatus CreateKeychain(SecKeychainRef* keychain) { | |
603 ASSERT(keychain != NULL); | |
604 OSStatus status = noErr; | |
605 const char* temp_keychain_pwd = "dartdart"; | |
606 char* temp_file_path = TempKeychainPath(); | |
607 ASSERT(temp_file_path != NULL); | |
608 if (SSL_LOG_CERTS) { | |
609 Log::Print("Temporary keychain at: '%s'\n", temp_file_path); | |
610 } | |
611 status = SecKeychainCreate(temp_file_path, | |
612 strlen(temp_keychain_pwd) + 1, | |
613 reinterpret_cast<const void*>(temp_keychain_pwd), | |
614 FALSE, // Prompt user? Definitely no. | |
615 NULL, // Default access rights. | |
616 keychain); | |
617 if (status != noErr) { | |
618 return status; | |
619 } | |
620 ASSERT(*keychain != NULL); | |
621 return status; | |
622 } | |
623 | |
624 | |
625 static OSStatus TryPKCS12Import(CFDataRef cfdata, | |
626 CFStringRef password, | |
627 CFArrayRef* out_certs, | |
628 SecKeyRef* out_key, | |
629 SecKeychainRef* out_keychain) { | |
630 OSStatus status = noErr; | |
631 | |
632 SecExternalFormat format = kSecFormatPKCS12; | |
633 SecExternalItemType sitem_type = kSecItemTypeAggregate; | |
634 | |
635 SecItemImportExportKeyParameters params; | |
636 memset(¶ms, 0, sizeof(params)); | |
637 params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; | |
638 params.flags = kSecKeyNoAccessControl; | |
639 params.passphrase = password; | |
640 | |
641 CFArrayRef items = NULL; | |
642 if (SSL_LOG_CERTS) { | |
643 Log::Print("Trying PKCS12 import with: type = %d, format = %d\n", | |
644 sitem_type, format); | |
645 } | |
646 | |
647 // The documentation for SecKeychainItemImport here: | |
648 // | |
649 // https://developer.apple.com/library/mac/documentation/Security/Reference/ke
ychainservices/index.html | |
650 // | |
651 // states that when the SecKeychainRef argument is NULL, the CFArrayRef* | |
652 // argument will be populated by an array containing all keys, identities, | |
653 // and certificates from the data in the CFDataRef argument. | |
654 // | |
655 // Unfortunately, this is not true. The code to populate the CFArrayRef with | |
656 // keys and identities from PKCS12 data has been skipped and/or commented out, | |
657 // here: | |
658 // | |
659 // https://github.com/Apple-FOSS-Mirror/Security/blob/master/libsecurity_keych
ain/lib/SecImportExportAgg.cpp#L636 | |
660 // | |
661 // as "floating" SecKeyRefs from the PKCS12 decoder haven't been implemented. | |
662 // That is, each private key instance coming from the PKCS12 decoder has to be | |
663 // associated with a keychain instance. Thus, as a workaround, we create a | |
664 // temporary keychain here if one is needed, and stash it below in a | |
665 // SecurityContext. This has the drawbacks: | |
666 // 1.) We need to make a temporary directory to hold the keychain file, and | |
667 // 2.) SecKeychainItemImport() probably does blocking IO to create and | |
668 // manipulate the keychain file. | |
669 // So if the API is updated, this keychain should not be used. | |
670 SecKeychainRef keychain = NULL; | |
671 if (out_key != NULL) { | |
672 ASSERT(out_keychain != NULL); | |
673 status = CreateKeychain(&keychain); | |
674 if (status != noErr) { | |
675 return status; | |
676 } | |
677 *out_keychain = keychain; | |
678 } | |
679 | |
680 status = SecItemImport( | |
681 cfdata, NULL, &format, &sitem_type, 0, ¶ms, keychain, &items); | |
682 if (status != noErr) { | |
683 if (SSL_LOG_CERTS) { | |
684 Log::Print("TrySecItemImport failed with: %ld, it = %d, format = %d\n", | |
685 static_cast<intptr_t>(status), sitem_type, format); | |
686 } | |
687 return status; | |
688 } | |
689 | |
690 CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items); | |
691 if (SSL_LOG_CERTS) { | |
692 Log::Print("TrySecItemImport succeeded, count = %ld\n", items_length); | |
693 } | |
694 | |
695 // Empty list indicates a decoding failure of some sort. | |
696 if ((items != NULL) && (items_length == 0)) { | |
697 CFRelease(items); | |
698 return errSSLBadCert; | |
699 } | |
700 | |
701 status = GetKeyAndCerts(items, items_length, out_certs, out_key); | |
702 CFRelease(items); | |
703 return status; | |
704 } | |
705 | |
706 | |
707 static OSStatus ExtractSecItems(uint8_t* buffer, | |
708 intptr_t length, | |
709 const char* password, | |
710 CFArrayRef* out_certs, | |
711 SecKeyRef* out_key, | |
712 SecKeychainRef* out_keychain) { | |
713 ASSERT(buffer != NULL); | |
714 ASSERT(password != NULL); | |
715 OSStatus status = noErr; | |
716 | |
717 CFDataRef cfdata = CFDataCreateWithBytesNoCopy( | |
718 NULL, buffer, length, kCFAllocatorNull); | |
719 CFStringRef cfpassword = CFStringCreateWithCStringNoCopy( | |
720 NULL, password, kCFStringEncodingUTF8, kCFAllocatorNull); | |
721 ASSERT(cfdata != NULL); | |
722 ASSERT(cfpassword != NULL); | |
723 | |
724 status = TryPEMImport(cfdata, cfpassword, out_certs, out_key); | |
725 if (status != noErr) { | |
726 status = | |
727 TryPKCS12Import(cfdata, cfpassword, out_certs, out_key, out_keychain); | |
728 } | |
729 | |
730 CFRelease(cfdata); | |
731 CFRelease(cfpassword); | |
732 return status; | |
733 } | |
734 | |
735 | |
736 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { | 250 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { |
737 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | 251 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
738 SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer. | 252 SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer. |
739 Dart_Handle err = SetFilter(args, filter); | 253 Dart_Handle err = SetFilter(args, filter); |
740 if (Dart_IsError(err)) { | 254 if (Dart_IsError(err)) { |
741 delete filter; | 255 delete filter; |
742 Dart_PropagateError(err); | 256 Dart_PropagateError(err); |
743 } | 257 } |
744 err = filter->Init(dart_this); | 258 err = filter->Init(dart_this); |
745 if (Dart_IsError(err)) { | 259 if (Dart_IsError(err)) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 Dart_Handle callback = | 350 Dart_Handle callback = |
837 ThrowIfError(Dart_GetNativeArgument(args, 1)); | 351 ThrowIfError(Dart_GetNativeArgument(args, 1)); |
838 if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) { | 352 if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) { |
839 Dart_ThrowException(DartUtils::NewDartArgumentError( | 353 Dart_ThrowException(DartUtils::NewDartArgumentError( |
840 "Illegal argument to RegisterBadCertificateCallback")); | 354 "Illegal argument to RegisterBadCertificateCallback")); |
841 } | 355 } |
842 GetFilter(args)->RegisterBadCertificateCallback(callback); | 356 GetFilter(args)->RegisterBadCertificateCallback(callback); |
843 } | 357 } |
844 | 358 |
845 | 359 |
846 void FUNCTION_NAME(SecureSocket_PeerCertificate) | 360 void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) { |
847 (Dart_NativeArguments args) { | |
848 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); | 361 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); |
849 } | 362 } |
850 | 363 |
851 | 364 |
852 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { | 365 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { |
853 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); | 366 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); |
854 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); | 367 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); |
855 } | 368 } |
856 | 369 |
857 | 370 |
858 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { | 371 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { |
859 SSLCertContext* cert_context = new SSLCertContext(); | 372 SSLCertContext* cert_context = new SSLCertContext(); |
860 // cert_context deleted in DeleteCertContext finalizer. | 373 // cert_context deleted in DeleteCertContext finalizer. |
861 Dart_Handle err = SetSecurityContext(args, cert_context); | 374 Dart_Handle err = SetSecurityContext(args, cert_context); |
862 if (Dart_IsError(err)) { | 375 if (Dart_IsError(err)) { |
863 delete cert_context; | 376 delete cert_context; |
864 Dart_PropagateError(err); | 377 Dart_PropagateError(err); |
865 } | 378 } |
866 } | 379 } |
867 | 380 |
868 | 381 |
869 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 382 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
870 Dart_NativeArguments args) { | 383 Dart_NativeArguments args) { |
871 SSLCertContext* context = GetSecurityContext(args); | 384 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
872 const char* password = GetPasswordArgument(args, 2); | 385 "SecurityContext.usePrivateKeyBytes is not yet implemented.")); |
873 | |
874 OSStatus status; | |
875 SecKeyRef key = NULL; | |
876 SecKeychainRef keychain = NULL; | |
877 { | |
878 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); | |
879 status = ExtractSecItems( | |
880 buffer.get(), buffer.length(), password, NULL, &key, &keychain); | |
881 } | |
882 | |
883 // Set the context fields. If there's a failure, release the items. | |
884 bool set_failure = false; | |
885 if ((key != NULL) && !context->set_private_key(key)) { | |
886 CFRelease(key); | |
887 SecKeychainDelete(keychain); | |
888 CFRelease(keychain); | |
889 set_failure = true; | |
890 } | |
891 if (!set_failure && (keychain != NULL) && !context->set_keychain(keychain)) { | |
892 SecKeychainDelete(keychain); | |
893 CFRelease(keychain); | |
894 } | |
895 | |
896 if (set_failure) { | |
897 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
898 "usePrivateKeyBytes has already been called on the given context.")); | |
899 } | |
900 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); | |
901 } | 386 } |
902 | 387 |
903 | 388 |
904 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 389 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
905 Dart_NativeArguments args) { | 390 Dart_NativeArguments args) { |
906 SSLCertContext* context = GetSecurityContext(args); | 391 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
907 const char* password = GetPasswordArgument(args, 2); | 392 "SecurityContext.setTrustedCertificatesBytes is not yet implemented.")); |
908 | |
909 OSStatus status; | |
910 CFArrayRef certs = NULL; | |
911 { | |
912 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); | |
913 status = ExtractSecItems( | |
914 buffer.get(), buffer.length(), password, &certs, NULL, NULL); | |
915 } | |
916 | |
917 // Set the field in the context. If there's a failure, release the certs, | |
918 // and throw an exception. | |
919 if ((certs != NULL) && !context->set_trusted_certs(certs)) { | |
920 CFRelease(certs); | |
921 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
922 "setTrustedCertificatesBytes has already been called " | |
923 "on the given context.")); | |
924 } | |
925 | |
926 CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes"); | |
927 } | 393 } |
928 | 394 |
929 | 395 |
930 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { | 396 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { |
931 Dart_SetReturnValue(args, Dart_NewBoolean(false)); | 397 Dart_SetReturnValue(args, Dart_NewBoolean(false)); |
932 } | 398 } |
933 | 399 |
934 | 400 |
935 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 401 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
936 Dart_NativeArguments args) { | 402 Dart_NativeArguments args) { |
937 SSLCertContext* context = GetSecurityContext(args); | 403 SSLCertContext* context = GetSecurityContext(args); |
938 context->set_trust_builtin(true); | 404 context->set_trust_builtin(true); |
939 } | 405 } |
940 | 406 |
941 | 407 |
942 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 408 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
943 Dart_NativeArguments args) { | 409 Dart_NativeArguments args) { |
944 SSLCertContext* context = GetSecurityContext(args); | 410 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
945 | 411 "SecurityContext.useCertificateChainBytes is not yet implemented.")); |
946 const char* password = GetPasswordArgument(args, 2); | |
947 OSStatus status; | |
948 CFArrayRef certs = NULL; | |
949 { | |
950 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); | |
951 status = ExtractSecItems( | |
952 buffer.get(), buffer.length(), password, &certs, NULL, NULL); | |
953 } | |
954 | |
955 // Set the field in the context. If there's a failure, release the certs, | |
956 // and throw an exception. | |
957 if ((certs != NULL) && !context->set_cert_chain(certs)) { | |
958 CFRelease(certs); | |
959 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
960 "useCertificateChainBytes has already been called " | |
961 "on the given context.")); | |
962 } | |
963 | |
964 CheckStatus(status, "TlsException", "Failure in useCertificateChainBytes"); | |
965 } | 412 } |
966 | 413 |
967 | 414 |
968 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 415 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
969 Dart_NativeArguments args) { | 416 Dart_NativeArguments args) { |
970 SSLCertContext* context = GetSecurityContext(args); | 417 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
971 const char* password = GetPasswordArgument(args, 2); | 418 "SecurityContext.setClientAuthoritiesBytes is not yet implemented.")); |
972 | |
973 OSStatus status; | |
974 CFArrayRef certs = NULL; | |
975 { | |
976 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); | |
977 status = ExtractSecItems( | |
978 buffer.get(), buffer.length(), password, &certs, NULL, NULL); | |
979 } | |
980 | |
981 // Set the field in the context. If there's a failure, release the certs, | |
982 // and throw an exception. | |
983 if ((certs != NULL) && !context->set_cert_authorities(certs)) { | |
984 CFRelease(certs); | |
985 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
986 "setClientAuthoritiesBytes has already been called " | |
987 "on the given context.")); | |
988 } | |
989 | |
990 CheckStatus(status, "TlsException", "Failure in setClientAuthoritiesBytes"); | |
991 } | 419 } |
992 | 420 |
993 | 421 |
994 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( | 422 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( |
995 Dart_NativeArguments args) { | 423 Dart_NativeArguments args) { |
996 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 424 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
997 "ALPN is not supported on this platform")); | 425 "ALPN is not supported on this platform")); |
998 } | 426 } |
999 | 427 |
1000 | 428 |
1001 static char* GetNameFromCert(SecCertificateRef certificate, | |
1002 CFTypeRef field, | |
1003 CFStringRef name) { | |
1004 char* issuer_name = NULL; | |
1005 | |
1006 CFTypeRef keys[] = { field }; | |
1007 CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks); | |
1008 CFErrorRef error = NULL; | |
1009 CFDictionaryRef cert_dict = | |
1010 SecCertificateCopyValues(certificate, key_array, &error); | |
1011 if (cert_dict == NULL) { | |
1012 CFRelease(key_array); | |
1013 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
1014 "X509.issuer failed to copy issuer field out of certificate")); | |
1015 } | |
1016 | |
1017 CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]); | |
1018 ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID()); | |
1019 CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item); | |
1020 | |
1021 item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue); | |
1022 ASSERT(CFGetTypeID(item) == CFArrayGetTypeID()); | |
1023 CFArrayRef val_array = reinterpret_cast<CFArrayRef>(item); | |
1024 | |
1025 for (intptr_t i = 0; i < CFArrayGetCount(val_array); i++) { | |
1026 item = CFArrayGetValueAtIndex(val_array, i); | |
1027 ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID()); | |
1028 CFDictionaryRef val_dict2 = reinterpret_cast<CFDictionaryRef>(item); | |
1029 | |
1030 item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyLabel); | |
1031 ASSERT(CFGetTypeID(item) == CFStringGetTypeID()); | |
1032 CFStringRef label = reinterpret_cast<CFStringRef>(item); | |
1033 | |
1034 if (CFStringCompare(label, name, 0) == kCFCompareEqualTo) { | |
1035 item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyValue); | |
1036 ASSERT(CFGetTypeID(item) == CFStringGetTypeID()); | |
1037 CFStringRef value = reinterpret_cast<CFStringRef>(item); | |
1038 issuer_name = CFStringRefToCString(value); | |
1039 break; | |
1040 } | |
1041 } | |
1042 | |
1043 CFRelease(cert_dict); | |
1044 CFRelease(key_array); | |
1045 return issuer_name; | |
1046 } | |
1047 | |
1048 | |
1049 void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) { | 429 void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) { |
1050 SecCertificateRef certificate = GetX509Certificate(args); | 430 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
1051 char* subject_name = GetNameFromCert( | 431 "X509Certificate.subject is not yet implemented.")); |
1052 certificate, | |
1053 kSecOIDX509V1SubjectName, | |
1054 reinterpret_cast<CFStringRef>(kSecOIDCommonName)); | |
1055 if (subject_name == NULL) { | |
1056 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
1057 "X509.subject failed to find issuer's common name.")); | |
1058 } else { | |
1059 Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_name)); | |
1060 } | |
1061 } | 432 } |
1062 | 433 |
1063 | 434 |
1064 void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) { | 435 void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) { |
1065 SecCertificateRef certificate = GetX509Certificate(args); | 436 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
1066 char* issuer_name = GetNameFromCert( | 437 "X509Certificate.issuer is not supported on this platform.")); |
1067 certificate, | |
1068 kSecOIDX509V1IssuerName, | |
1069 reinterpret_cast<CFStringRef>(kSecOIDCommonName)); | |
1070 if (issuer_name == NULL) { | |
1071 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
1072 "X509.issuer failed to find issuer's common name.")); | |
1073 } else { | |
1074 Dart_SetReturnValue(args, Dart_NewStringFromCString(issuer_name)); | |
1075 } | |
1076 } | |
1077 | |
1078 | |
1079 // Returns the number of seconds since the epoch from 'field'. | |
1080 static int64_t GetTimeFromCert(SecCertificateRef certificate, CFTypeRef field) { | |
1081 CFTypeRef keys[] = { field }; | |
1082 CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks); | |
1083 CFErrorRef error = NULL; | |
1084 CFDictionaryRef cert_dict = | |
1085 SecCertificateCopyValues(certificate, key_array, &error); | |
1086 if (cert_dict == NULL) { | |
1087 CFRelease(key_array); | |
1088 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
1089 "X509.startValidity: failed to copy issuer field out of certificate")); | |
1090 } | |
1091 | |
1092 CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]); | |
1093 ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID()); | |
1094 CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item); | |
1095 | |
1096 item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue); | |
1097 ASSERT(CFGetTypeID(item) == CFNumberGetTypeID()); | |
1098 CFNumberRef date_number = reinterpret_cast<CFNumberRef>(item); | |
1099 | |
1100 CFAbsoluteTime date_abs_time; | |
1101 CFNumberGetValue(date_number, kCFNumberDoubleType, &date_abs_time); | |
1102 CFAbsoluteTime seconds_since_epoch = | |
1103 date_abs_time + kCFAbsoluteTimeIntervalSince1970; | |
1104 return static_cast<int64_t>(seconds_since_epoch) * 1000LL; | |
1105 } | 438 } |
1106 | 439 |
1107 | 440 |
1108 void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) { | 441 void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) { |
1109 SecCertificateRef certificate = GetX509Certificate(args); | 442 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
1110 int64_t seconds_since_epoch = GetTimeFromCert(certificate, | 443 "X509Certificate.startValidity is not supported on this platform.")); |
1111 kSecOIDX509V1ValidityNotBefore); | |
1112 Dart_SetReturnValue(args, | |
1113 Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL)); | |
1114 } | 444 } |
1115 | 445 |
1116 | 446 |
1117 void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) { | 447 void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) { |
1118 SecCertificateRef certificate = GetX509Certificate(args); | 448 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
1119 int64_t seconds_since_epoch = GetTimeFromCert(certificate, | 449 "X509Certificate.endValidity is not supported on this platform.")); |
1120 kSecOIDX509V1ValidityNotAfter); | |
1121 Dart_SetReturnValue(args, | |
1122 Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL)); | |
1123 } | 450 } |
1124 | 451 |
1125 | 452 |
1126 // Pushes data through the SSL filter, reading and writing from circular | 453 // Pushes data through the SSL filter, reading and writing from circular |
1127 // buffers shared with Dart. Called from the IOService thread. | 454 // buffers shared with Dart. Called from the IOService thread. |
1128 // | 455 // |
1129 // The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to | 456 // The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to |
1130 // pass encrypted and plaintext data to and from the C++ SSLFilter object. | 457 // pass encrypted and plaintext data to and from the C++ SSLFilter object. |
1131 // | 458 // |
1132 // ProcessFilter is called with a CObject array containing the pointer to | 459 // ProcessFilter is called with a CObject array containing the pointer to |
(...skipping 24 matching lines...) Expand all Loading... |
1157 if (status == noErr) { | 484 if (status == noErr) { |
1158 CObjectArray* result = new CObjectArray( | 485 CObjectArray* result = new CObjectArray( |
1159 CObject::NewArray(SSLFilter::kNumBuffers * 2)); | 486 CObject::NewArray(SSLFilter::kNumBuffers * 2)); |
1160 for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) { | 487 for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) { |
1161 result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i]))); | 488 result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i]))); |
1162 result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i]))); | 489 result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i]))); |
1163 } | 490 } |
1164 return result; | 491 return result; |
1165 } else { | 492 } else { |
1166 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); | 493 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); |
1167 CFStringRef error_string = SecCopyErrorMessageString(status, NULL); | 494 status_message.Printf("OSStatus = %ld: https://www.osstatus.com", |
1168 if (error_string == NULL) { | 495 static_cast<intptr_t>(status)); |
1169 status_message.Printf("OSStatus = %ld: https://www.osstatus.com", | |
1170 static_cast<intptr_t>(status)); | |
1171 } else { | |
1172 char* error = CFStringRefToCString(error_string); | |
1173 status_message.Printf("OSStatus = %ld: %s", | |
1174 static_cast<intptr_t>(status), error); | |
1175 CFRelease(error_string); | |
1176 } | |
1177 CObjectArray* result = new CObjectArray(CObject::NewArray(2)); | 496 CObjectArray* result = new CObjectArray(CObject::NewArray(2)); |
1178 result->SetAt(0, new CObjectInt32(CObject::NewInt32(status))); | 497 result->SetAt(0, new CObjectInt32(CObject::NewInt32(status))); |
1179 result->SetAt(1, new CObjectString(CObject::NewString( | 498 result->SetAt(1, new CObjectString(CObject::NewString( |
1180 status_message.buf()))); | 499 status_message.buf()))); |
1181 return result; | 500 return result; |
1182 } | 501 } |
1183 } | 502 } |
1184 | 503 |
1185 | 504 |
1186 // Usually buffer_starts_ and buffer_ends_ are populated by ProcessAllBuffers, | 505 // Usually buffer_starts_ and buffer_ends_ are populated by ProcessAllBuffers, |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 ssl_context, kSSLSessionOptionBreakOnServerAuth, true); | 831 ssl_context, kSSLSessionOptionBreakOnServerAuth, true); |
1513 CheckStatus(status, | 832 CheckStatus(status, |
1514 "TlsException", | 833 "TlsException", |
1515 "Failed to set BreakOnServerAuth option"); | 834 "Failed to set BreakOnServerAuth option"); |
1516 | 835 |
1517 status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1); | 836 status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1); |
1518 CheckStatus(status, | 837 CheckStatus(status, |
1519 "TlsException", | 838 "TlsException", |
1520 "Failed to set minimum protocol version to kTLSProtocol1"); | 839 "Failed to set minimum protocol version to kTLSProtocol1"); |
1521 | 840 |
1522 // If the context has a private key and certificate chain, combine the | |
1523 // private key and first certificate into a SecIdentityRef, and place that | |
1524 // and the remaining certs in an array to pass to SSLSetCertificate(). | |
1525 if ((context->private_key() != NULL) && (context->cert_chain() != NULL)) { | |
1526 CFIndex chain_length = CFArrayGetCount(context->cert_chain()); | |
1527 CFMutableArrayRef certs = | |
1528 CFArrayCreateMutable(NULL, chain_length, &kCFTypeArrayCallBacks); | |
1529 CFTypeRef item = CFArrayGetValueAtIndex(context->cert_chain(), 0); | |
1530 ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID()); | |
1531 SecCertificateRef first_cert = | |
1532 reinterpret_cast<SecCertificateRef>(const_cast<void*>(item)); | |
1533 SecIdentityRef identity = | |
1534 SecIdentityCreate(NULL, first_cert, context->private_key()); | |
1535 CFArrayAppendValue(certs, identity); | |
1536 for (CFIndex i = 0; i < chain_length; i++) { | |
1537 CFArrayAppendValue(certs, | |
1538 CFArrayGetValueAtIndex(context->cert_chain(), i)); | |
1539 } | |
1540 CFRelease(identity); | |
1541 status = SSLSetCertificate(ssl_context, certs); | |
1542 CFRelease(certs); | |
1543 CheckStatus(status, "TlsException", "SSLSetCertificate failed"); | |
1544 } | |
1545 | |
1546 if (context->cert_authorities() != NULL) { | |
1547 status = SSLSetCertificateAuthorities( | |
1548 ssl_context, context->cert_authorities(), true); | |
1549 CheckStatus(status, | |
1550 "TlsException", | |
1551 "Failed to set certificate authorities"); | |
1552 } | |
1553 | |
1554 if (is_server) { | 841 if (is_server) { |
1555 SSLAuthenticate auth = | 842 SSLAuthenticate auth = |
1556 require_client_certificate | 843 require_client_certificate |
1557 ? kAlwaysAuthenticate | 844 ? kAlwaysAuthenticate |
1558 : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate); | 845 : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate); |
1559 status = SSLSetClientSideAuthenticate(ssl_context, auth); | 846 status = SSLSetClientSideAuthenticate(ssl_context, auth); |
1560 CheckStatus(status, | 847 CheckStatus(status, |
1561 "TlsException", | 848 "TlsException", |
1562 "Failed to set client authentication mode"); | 849 "Failed to set client authentication mode"); |
1563 | 850 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1604 // A client certificate was requested, but not required, and wasn't sent. | 891 // A client certificate was requested, but not required, and wasn't sent. |
1605 return noErr; | 892 return noErr; |
1606 } | 893 } |
1607 if (SSL_LOG_STATUS) { | 894 if (SSL_LOG_STATUS) { |
1608 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", | 895 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", |
1609 static_cast<intptr_t>(status)); | 896 static_cast<intptr_t>(status)); |
1610 } | 897 } |
1611 return status; | 898 return status; |
1612 } | 899 } |
1613 | 900 |
1614 CFArrayRef trusted_certs = NULL; | 901 CFArrayRef trusted_certs = |
1615 if (cert_context_->trusted_certs() != NULL) { | 902 CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); |
1616 trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs()); | |
1617 } else { | |
1618 trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); | |
1619 } | |
1620 | 903 |
1621 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); | 904 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); |
1622 if (status != noErr) { | 905 if (status != noErr) { |
1623 if (SSL_LOG_STATUS) { | 906 if (SSL_LOG_STATUS) { |
1624 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", | 907 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", |
1625 static_cast<intptr_t>(status)); | 908 static_cast<intptr_t>(status)); |
1626 } | 909 } |
1627 CFRelease(trusted_certs); | 910 CFRelease(trusted_certs); |
1628 CFRelease(peer_trust); | 911 CFRelease(peer_trust); |
1629 return status; | 912 return status; |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2015 Log::Print("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n", | 1298 Log::Print("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n", |
2016 length, bytes); | 1299 length, bytes); |
2017 } | 1300 } |
2018 *bytes_processed = static_cast<intptr_t>(bytes); | 1301 *bytes_processed = static_cast<intptr_t>(bytes); |
2019 return status; | 1302 return status; |
2020 } | 1303 } |
2021 | 1304 |
2022 } // namespace bin | 1305 } // namespace bin |
2023 } // namespace dart | 1306 } // namespace dart |
2024 | 1307 |
2025 #endif // defined(TARGET_OS_MACOS) | 1308 #endif // TARGET_OS_IOS |
2026 | 1309 |
2027 #endif // !defined(DART_IO_DISABLED) && | 1310 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
2028 // !defined(DART_IO_SECURE_SOCKET_DISABLED) | |
OLD | NEW |