| Index: runtime/bin/secure_socket_ios.cc
|
| diff --git a/runtime/bin/secure_socket_macos.cc b/runtime/bin/secure_socket_ios.cc
|
| similarity index 63%
|
| copy from runtime/bin/secure_socket_macos.cc
|
| copy to runtime/bin/secure_socket_ios.cc
|
| index 5e6e320f20cca2c007e667170dbe67e70a72dcc0..c52ffb73b5a3db8d529be8d107d686899fc1d367 100644
|
| --- a/runtime/bin/secure_socket_macos.cc
|
| +++ b/runtime/bin/secure_socket_ios.cc
|
| @@ -5,7 +5,7 @@
|
| #if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
|
|
|
| #include "platform/globals.h"
|
| -#if defined(TARGET_OS_MACOS)
|
| +#if TARGET_OS_IOS
|
|
|
| #include "bin/secure_socket.h"
|
| #include "bin/secure_socket_macos.h"
|
| @@ -62,9 +62,7 @@ static const int kX509NativeFieldIndex = 0;
|
|
|
| static const bool SSL_LOG_STATUS = false;
|
| static const bool SSL_LOG_DATA = false;
|
| -static const bool SSL_LOG_CERTS = false;
|
| static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
|
| -static const intptr_t PEM_BUFSIZE = 1024;
|
|
|
| // SSLCertContext wraps the certificates needed for a SecureTransport
|
| // connection. Fields are protected by the mutex_ field, and may only be set
|
| @@ -74,98 +72,12 @@ class SSLCertContext {
|
| public:
|
| SSLCertContext() :
|
| mutex_(new Mutex()),
|
| - private_key_(NULL),
|
| - keychain_(NULL),
|
| - cert_chain_(NULL),
|
| - trusted_certs_(NULL),
|
| - cert_authorities_(NULL),
|
| trust_builtin_(false) {}
|
|
|
| ~SSLCertContext() {
|
| - if (private_key_ != NULL) {
|
| - CFRelease(private_key_);
|
| - }
|
| - if (keychain_ != NULL) {
|
| - SecKeychainDelete(keychain_);
|
| - CFRelease(keychain_);
|
| - }
|
| - if (cert_chain_ != NULL) {
|
| - CFRelease(cert_chain_);
|
| - }
|
| - if (trusted_certs_ != NULL) {
|
| - CFRelease(trusted_certs_);
|
| - }
|
| - if (cert_authorities_ != NULL) {
|
| - CFRelease(cert_authorities_);
|
| - }
|
| delete mutex_;
|
| }
|
|
|
| - SecKeyRef private_key() {
|
| - MutexLocker m(mutex_);
|
| - return private_key_;
|
| - }
|
| - bool set_private_key(SecKeyRef private_key) {
|
| - MutexLocker m(mutex_);
|
| - if (private_key_ != NULL) {
|
| - return false;
|
| - }
|
| - private_key_ = private_key;
|
| - return true;
|
| - }
|
| -
|
| - SecKeychainRef keychain() {
|
| - MutexLocker m(mutex_);
|
| - return keychain_;
|
| - }
|
| - bool set_keychain(SecKeychainRef keychain) {
|
| - MutexLocker m(mutex_);
|
| - if (keychain_ != NULL) {
|
| - return false;
|
| - }
|
| - keychain_ = keychain;
|
| - return true;
|
| - }
|
| -
|
| - CFArrayRef cert_chain() {
|
| - MutexLocker m(mutex_);
|
| - return cert_chain_;
|
| - }
|
| - bool set_cert_chain(CFArrayRef cert_chain) {
|
| - MutexLocker m(mutex_);
|
| - if (cert_chain_ != NULL) {
|
| - return false;
|
| - }
|
| - cert_chain_ = cert_chain;
|
| - return true;
|
| - }
|
| -
|
| - CFArrayRef trusted_certs() {
|
| - MutexLocker m(mutex_);
|
| - return trusted_certs_;
|
| - }
|
| - bool set_trusted_certs(CFArrayRef trusted_certs) {
|
| - MutexLocker m(mutex_);
|
| - if (trusted_certs_ != NULL) {
|
| - return false;
|
| - }
|
| - trusted_certs_ = trusted_certs;
|
| - return true;
|
| - }
|
| -
|
| - CFArrayRef cert_authorities() {
|
| - MutexLocker m(mutex_);
|
| - return cert_authorities_;
|
| - }
|
| - bool set_cert_authorities(CFArrayRef cert_authorities) {
|
| - MutexLocker m(mutex_);
|
| - if (cert_authorities_ != NULL) {
|
| - return false;
|
| - }
|
| - cert_authorities_ = cert_authorities;
|
| - return true;
|
| - }
|
| -
|
| bool trust_builtin() {
|
| MutexLocker m(mutex_);
|
| return trust_builtin_;
|
| @@ -179,48 +91,18 @@ class SSLCertContext {
|
| // The context is accessed both by Dart code and the IOService. This mutex
|
| // protects all fields.
|
| Mutex* mutex_;
|
| -
|
| - SecKeyRef private_key_;
|
| - SecKeychainRef keychain_;
|
| -
|
| - // CFArrays of SecCertificateRef.
|
| - CFArrayRef cert_chain_;
|
| - CFArrayRef trusted_certs_;
|
| - CFArrayRef cert_authorities_;
|
| -
|
| bool trust_builtin_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
|
| };
|
|
|
| -
|
| -static char* CFStringRefToCString(CFStringRef cfstring) {
|
| - CFIndex len = CFStringGetLength(cfstring);
|
| - CFIndex max_len =
|
| - CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1;
|
| - char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(max_len));
|
| - ASSERT(result != NULL);
|
| - bool success =
|
| - CFStringGetCString(cfstring, result, max_len, kCFStringEncodingUTF8);
|
| - return success ? result : NULL;
|
| -}
|
| -
|
| -
|
| // Handle an error reported from the SecureTransport library.
|
| static void ThrowIOException(OSStatus status,
|
| const char* exception_type,
|
| const char* message) {
|
| TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
|
| - CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
|
| - if (error_string == NULL) {
|
| - status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
|
| - static_cast<intptr_t>(status));
|
| - } else {
|
| - char* error = CFStringRefToCString(error_string);
|
| - status_message.Printf("OSStatus = %ld: %s",
|
| - static_cast<intptr_t>(status), error);
|
| - CFRelease(error_string);
|
| - }
|
| + status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
|
| + static_cast<intptr_t>(status));
|
| OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL);
|
| Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
|
| Dart_Handle exception =
|
| @@ -319,18 +201,6 @@ static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
|
| }
|
|
|
|
|
| -static SecCertificateRef GetX509Certificate(Dart_NativeArguments args) {
|
| - SecCertificateRef certificate;
|
| - Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
|
| - ASSERT(Dart_IsInstance(dart_this));
|
| - ThrowIfError(Dart_GetNativeInstanceField(
|
| - dart_this,
|
| - kX509NativeFieldIndex,
|
| - reinterpret_cast<intptr_t*>(&certificate)));
|
| - return certificate;
|
| -}
|
| -
|
| -
|
| static void ReleaseCertificate(void* isolate_data,
|
| Dart_WeakPersistentHandle handle,
|
| void* context_pointer) {
|
| @@ -377,362 +247,6 @@ static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) {
|
| }
|
|
|
|
|
| -// Where the argument to the constructor is the handle for an object
|
| -// implementing List<int>, this class creates a scope in which the memory
|
| -// backing the list can be accessed.
|
| -//
|
| -// Do not make Dart_ API calls while in a ScopedMemBuffer.
|
| -// Do not call Dart_PropagateError while in a ScopedMemBuffer.
|
| -class ScopedMemBuffer {
|
| - public:
|
| - explicit ScopedMemBuffer(Dart_Handle object) {
|
| - if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "Argument is not a List<int>"));
|
| - }
|
| -
|
| - uint8_t* bytes = NULL;
|
| - intptr_t bytes_len = 0;
|
| - bool is_typed_data = false;
|
| - if (Dart_IsTypedData(object)) {
|
| - is_typed_data = true;
|
| - Dart_TypedData_Type typ;
|
| - ThrowIfError(Dart_TypedDataAcquireData(
|
| - object,
|
| - &typ,
|
| - reinterpret_cast<void**>(&bytes),
|
| - &bytes_len));
|
| - } else {
|
| - ASSERT(Dart_IsList(object));
|
| - ThrowIfError(Dart_ListLength(object, &bytes_len));
|
| - bytes = Dart_ScopeAllocate(bytes_len);
|
| - ASSERT(bytes != NULL);
|
| - ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len));
|
| - }
|
| -
|
| - object_ = object;
|
| - bytes_ = bytes;
|
| - bytes_len_ = bytes_len;
|
| - is_typed_data_ = is_typed_data;
|
| - }
|
| -
|
| - ~ScopedMemBuffer() {
|
| - if (is_typed_data_) {
|
| - ThrowIfError(Dart_TypedDataReleaseData(object_));
|
| - }
|
| - }
|
| -
|
| - uint8_t* get() const { return bytes_; }
|
| - intptr_t length() const { return bytes_len_; }
|
| -
|
| - private:
|
| - Dart_Handle object_;
|
| - uint8_t* bytes_;
|
| - intptr_t bytes_len_;
|
| - bool is_typed_data_;
|
| -
|
| - DISALLOW_ALLOCATION();
|
| - DISALLOW_COPY_AND_ASSIGN(ScopedMemBuffer);
|
| -};
|
| -
|
| -
|
| -static const char* GetPasswordArgument(Dart_NativeArguments args,
|
| - intptr_t index) {
|
| - Dart_Handle password_object =
|
| - ThrowIfError(Dart_GetNativeArgument(args, index));
|
| - const char* password = NULL;
|
| - if (Dart_IsString(password_object)) {
|
| - ThrowIfError(Dart_StringToCString(password_object, &password));
|
| - if (strlen(password) > PEM_BUFSIZE - 1) {
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "Password length is greater than 1023 bytes."));
|
| - }
|
| - } else if (Dart_IsNull(password_object)) {
|
| - password = "";
|
| - } else {
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "Password is not a String or null"));
|
| - }
|
| - return password;
|
| -}
|
| -
|
| -
|
| -static OSStatus GetKeyAndCerts(CFArrayRef items,
|
| - CFIndex items_length,
|
| - CFArrayRef* out_certs,
|
| - SecKeyRef* out_key) {
|
| - OSStatus status = noErr;
|
| -
|
| - // Loop through the items, take only the first private key/identity, ignore
|
| - // any others, populate out_certs.
|
| - CFMutableArrayRef certs =
|
| - CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
| - SecKeyRef key = NULL;
|
| -
|
| - for (CFIndex i = 0; i < items_length; ++i) {
|
| - CFTypeRef item =
|
| - reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i));
|
| - CFTypeID item_type = CFGetTypeID(item);
|
| - if (item_type == SecCertificateGetTypeID()) {
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("\titem %ld: Certificate\n", i);
|
| - }
|
| - CFArrayAppendValue(certs, item);
|
| - } else if ((item_type == SecKeyGetTypeID()) && (key == NULL)) {
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("\titem %ld: Key\n", i);
|
| - }
|
| - key = reinterpret_cast<SecKeyRef>(const_cast<void*>(item));
|
| - CFRetain(key);
|
| - } else if ((item_type == SecIdentityGetTypeID()) && (key == NULL)) {
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("\titem %ld: Identity\n", i);
|
| - }
|
| - SecIdentityRef identity =
|
| - reinterpret_cast<SecIdentityRef>(const_cast<void*>(item));
|
| - SecCertificateRef cert = NULL;
|
| -
|
| - status = SecIdentityCopyPrivateKey(identity, &key);
|
| - if (status != noErr) {
|
| - CFRelease(certs);
|
| - return status;
|
| - }
|
| -
|
| - status = SecIdentityCopyCertificate(identity, &cert);
|
| - if (status != noErr) {
|
| - CFRelease(key);
|
| - CFRelease(certs);
|
| - return status;
|
| - }
|
| - CFArrayAppendValue(certs, cert);
|
| - CFRelease(cert);
|
| - }
|
| - // Other item types are ignored.
|
| - }
|
| -
|
| - if (out_key == NULL) {
|
| - if (key != NULL) {
|
| - CFRelease(key);
|
| - }
|
| - } else {
|
| - *out_key = key;
|
| - }
|
| -
|
| - if (out_certs == NULL) {
|
| - if (certs != NULL) {
|
| - CFRelease(certs);
|
| - }
|
| - } else {
|
| - *out_certs = certs;
|
| - }
|
| - return status;
|
| -}
|
| -
|
| -
|
| -static OSStatus TryPEMImport(CFDataRef cfdata,
|
| - CFStringRef password,
|
| - CFArrayRef* out_certs,
|
| - SecKeyRef* out_key) {
|
| - OSStatus status = noErr;
|
| -
|
| - SecExternalFormat format = kSecFormatPEMSequence;
|
| - SecExternalItemType sitem_type = kSecItemTypeAggregate;
|
| -
|
| - SecItemImportExportKeyParameters params;
|
| - memset(¶ms, 0, sizeof(params));
|
| - params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
|
| - params.flags = kSecKeyNoAccessControl;
|
| - params.passphrase = password;
|
| -
|
| - CFArrayRef items = NULL;
|
| - status = SecItemImport(
|
| - cfdata, NULL, &format, &sitem_type, 0, ¶ms, NULL, &items);
|
| -
|
| - if (status != noErr) {
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("TrySecItemImport failed with: %ld, type = %d, format = %d\n",
|
| - static_cast<intptr_t>(status), sitem_type, format);
|
| - }
|
| - return status;
|
| - }
|
| -
|
| - CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print(
|
| - "TrySecItemImport succeeded, type = %d, format = %d, count = %ld\n",
|
| - sitem_type, format, items_length);
|
| - }
|
| -
|
| - // Empty list indicates a decoding failure of some sort.
|
| - if ((items != NULL) && (items_length == 0)) {
|
| - CFRelease(items);
|
| - return errSSLBadCert;
|
| - }
|
| -
|
| - status = GetKeyAndCerts(items, items_length, out_certs, out_key);
|
| - CFRelease(items);
|
| - return status;
|
| -}
|
| -
|
| -
|
| -static char* TempKeychainPath() {
|
| - const char* exes = "keychaindir.XXXX";
|
| - const char* fname = "keychain";
|
| - const char* temp_dir = getenv("TMPDIR");
|
| - if (temp_dir == NULL) {
|
| - temp_dir = getenv("TMP");
|
| - }
|
| - if (temp_dir == NULL) {
|
| - temp_dir = "/tmp/";
|
| - }
|
| - ASSERT(temp_dir != NULL);
|
| -
|
| - TextBuffer path(PATH_MAX);
|
| - path.Printf("%s/%s", temp_dir, exes);
|
| - char* ret = mkdtemp(path.buf());
|
| - ASSERT(ret != NULL);
|
| - path.Printf("/%s", fname);
|
| -
|
| - char* result =
|
| - reinterpret_cast<char*>(Dart_ScopeAllocate(path.length() + 1));
|
| - return strncpy(result, path.buf(), path.length() + 1);
|
| -}
|
| -
|
| -
|
| -static OSStatus CreateKeychain(SecKeychainRef* keychain) {
|
| - ASSERT(keychain != NULL);
|
| - OSStatus status = noErr;
|
| - const char* temp_keychain_pwd = "dartdart";
|
| - char* temp_file_path = TempKeychainPath();
|
| - ASSERT(temp_file_path != NULL);
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("Temporary keychain at: '%s'\n", temp_file_path);
|
| - }
|
| - status = SecKeychainCreate(temp_file_path,
|
| - strlen(temp_keychain_pwd) + 1,
|
| - reinterpret_cast<const void*>(temp_keychain_pwd),
|
| - FALSE, // Prompt user? Definitely no.
|
| - NULL, // Default access rights.
|
| - keychain);
|
| - if (status != noErr) {
|
| - return status;
|
| - }
|
| - ASSERT(*keychain != NULL);
|
| - return status;
|
| -}
|
| -
|
| -
|
| -static OSStatus TryPKCS12Import(CFDataRef cfdata,
|
| - CFStringRef password,
|
| - CFArrayRef* out_certs,
|
| - SecKeyRef* out_key,
|
| - SecKeychainRef* out_keychain) {
|
| - OSStatus status = noErr;
|
| -
|
| - SecExternalFormat format = kSecFormatPKCS12;
|
| - SecExternalItemType sitem_type = kSecItemTypeAggregate;
|
| -
|
| - SecItemImportExportKeyParameters params;
|
| - memset(¶ms, 0, sizeof(params));
|
| - params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
|
| - params.flags = kSecKeyNoAccessControl;
|
| - params.passphrase = password;
|
| -
|
| - CFArrayRef items = NULL;
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("Trying PKCS12 import with: type = %d, format = %d\n",
|
| - sitem_type, format);
|
| - }
|
| -
|
| - // The documentation for SecKeychainItemImport here:
|
| - //
|
| - // https://developer.apple.com/library/mac/documentation/Security/Reference/keychainservices/index.html
|
| - //
|
| - // states that when the SecKeychainRef argument is NULL, the CFArrayRef*
|
| - // argument will be populated by an array containing all keys, identities,
|
| - // and certificates from the data in the CFDataRef argument.
|
| - //
|
| - // Unfortunately, this is not true. The code to populate the CFArrayRef with
|
| - // keys and identities from PKCS12 data has been skipped and/or commented out,
|
| - // here:
|
| - //
|
| - // https://github.com/Apple-FOSS-Mirror/Security/blob/master/libsecurity_keychain/lib/SecImportExportAgg.cpp#L636
|
| - //
|
| - // as "floating" SecKeyRefs from the PKCS12 decoder haven't been implemented.
|
| - // That is, each private key instance coming from the PKCS12 decoder has to be
|
| - // associated with a keychain instance. Thus, as a workaround, we create a
|
| - // temporary keychain here if one is needed, and stash it below in a
|
| - // SecurityContext. This has the drawbacks:
|
| - // 1.) We need to make a temporary directory to hold the keychain file, and
|
| - // 2.) SecKeychainItemImport() probably does blocking IO to create and
|
| - // manipulate the keychain file.
|
| - // So if the API is updated, this keychain should not be used.
|
| - SecKeychainRef keychain = NULL;
|
| - if (out_key != NULL) {
|
| - ASSERT(out_keychain != NULL);
|
| - status = CreateKeychain(&keychain);
|
| - if (status != noErr) {
|
| - return status;
|
| - }
|
| - *out_keychain = keychain;
|
| - }
|
| -
|
| - status = SecItemImport(
|
| - cfdata, NULL, &format, &sitem_type, 0, ¶ms, keychain, &items);
|
| - if (status != noErr) {
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("TrySecItemImport failed with: %ld, it = %d, format = %d\n",
|
| - static_cast<intptr_t>(status), sitem_type, format);
|
| - }
|
| - return status;
|
| - }
|
| -
|
| - CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
|
| - if (SSL_LOG_CERTS) {
|
| - Log::Print("TrySecItemImport succeeded, count = %ld\n", items_length);
|
| - }
|
| -
|
| - // Empty list indicates a decoding failure of some sort.
|
| - if ((items != NULL) && (items_length == 0)) {
|
| - CFRelease(items);
|
| - return errSSLBadCert;
|
| - }
|
| -
|
| - status = GetKeyAndCerts(items, items_length, out_certs, out_key);
|
| - CFRelease(items);
|
| - return status;
|
| -}
|
| -
|
| -
|
| -static OSStatus ExtractSecItems(uint8_t* buffer,
|
| - intptr_t length,
|
| - const char* password,
|
| - CFArrayRef* out_certs,
|
| - SecKeyRef* out_key,
|
| - SecKeychainRef* out_keychain) {
|
| - ASSERT(buffer != NULL);
|
| - ASSERT(password != NULL);
|
| - OSStatus status = noErr;
|
| -
|
| - CFDataRef cfdata = CFDataCreateWithBytesNoCopy(
|
| - NULL, buffer, length, kCFAllocatorNull);
|
| - CFStringRef cfpassword = CFStringCreateWithCStringNoCopy(
|
| - NULL, password, kCFStringEncodingUTF8, kCFAllocatorNull);
|
| - ASSERT(cfdata != NULL);
|
| - ASSERT(cfpassword != NULL);
|
| -
|
| - status = TryPEMImport(cfdata, cfpassword, out_certs, out_key);
|
| - if (status != noErr) {
|
| - status =
|
| - TryPKCS12Import(cfdata, cfpassword, out_certs, out_key, out_keychain);
|
| - }
|
| -
|
| - CFRelease(cfdata);
|
| - CFRelease(cfpassword);
|
| - return status;
|
| -}
|
| -
|
| -
|
| void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
|
| Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
|
| SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer.
|
| @@ -843,8 +357,7 @@ void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
|
| }
|
|
|
|
|
| -void FUNCTION_NAME(SecureSocket_PeerCertificate)
|
| - (Dart_NativeArguments args) {
|
| +void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) {
|
| Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
|
| }
|
|
|
| @@ -868,62 +381,15 @@ void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
|
|
|
| void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
|
| Dart_NativeArguments args) {
|
| - SSLCertContext* context = GetSecurityContext(args);
|
| - const char* password = GetPasswordArgument(args, 2);
|
| -
|
| - OSStatus status;
|
| - SecKeyRef key = NULL;
|
| - SecKeychainRef keychain = NULL;
|
| - {
|
| - ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
|
| - status = ExtractSecItems(
|
| - buffer.get(), buffer.length(), password, NULL, &key, &keychain);
|
| - }
|
| -
|
| - // Set the context fields. If there's a failure, release the items.
|
| - bool set_failure = false;
|
| - if ((key != NULL) && !context->set_private_key(key)) {
|
| - CFRelease(key);
|
| - SecKeychainDelete(keychain);
|
| - CFRelease(keychain);
|
| - set_failure = true;
|
| - }
|
| - if (!set_failure && (keychain != NULL) && !context->set_keychain(keychain)) {
|
| - SecKeychainDelete(keychain);
|
| - CFRelease(keychain);
|
| - }
|
| -
|
| - if (set_failure) {
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "usePrivateKeyBytes has already been called on the given context."));
|
| - }
|
| - CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes");
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "SecurityContext.usePrivateKeyBytes is not yet implemented."));
|
| }
|
|
|
|
|
| void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
|
| Dart_NativeArguments args) {
|
| - SSLCertContext* context = GetSecurityContext(args);
|
| - const char* password = GetPasswordArgument(args, 2);
|
| -
|
| - OSStatus status;
|
| - CFArrayRef certs = NULL;
|
| - {
|
| - ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
|
| - status = ExtractSecItems(
|
| - buffer.get(), buffer.length(), password, &certs, NULL, NULL);
|
| - }
|
| -
|
| - // Set the field in the context. If there's a failure, release the certs,
|
| - // and throw an exception.
|
| - if ((certs != NULL) && !context->set_trusted_certs(certs)) {
|
| - CFRelease(certs);
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "setTrustedCertificatesBytes has already been called "
|
| - "on the given context."));
|
| - }
|
| -
|
| - CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes");
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "SecurityContext.setTrustedCertificatesBytes is not yet implemented."));
|
| }
|
|
|
|
|
| @@ -941,53 +407,15 @@ void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
|
|
|
| void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
|
| Dart_NativeArguments args) {
|
| - SSLCertContext* context = GetSecurityContext(args);
|
| -
|
| - const char* password = GetPasswordArgument(args, 2);
|
| - OSStatus status;
|
| - CFArrayRef certs = NULL;
|
| - {
|
| - ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
|
| - status = ExtractSecItems(
|
| - buffer.get(), buffer.length(), password, &certs, NULL, NULL);
|
| - }
|
| -
|
| - // Set the field in the context. If there's a failure, release the certs,
|
| - // and throw an exception.
|
| - if ((certs != NULL) && !context->set_cert_chain(certs)) {
|
| - CFRelease(certs);
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "useCertificateChainBytes has already been called "
|
| - "on the given context."));
|
| - }
|
| -
|
| - CheckStatus(status, "TlsException", "Failure in useCertificateChainBytes");
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "SecurityContext.useCertificateChainBytes is not yet implemented."));
|
| }
|
|
|
|
|
| void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
|
| Dart_NativeArguments args) {
|
| - SSLCertContext* context = GetSecurityContext(args);
|
| - const char* password = GetPasswordArgument(args, 2);
|
| -
|
| - OSStatus status;
|
| - CFArrayRef certs = NULL;
|
| - {
|
| - ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
|
| - status = ExtractSecItems(
|
| - buffer.get(), buffer.length(), password, &certs, NULL, NULL);
|
| - }
|
| -
|
| - // Set the field in the context. If there's a failure, release the certs,
|
| - // and throw an exception.
|
| - if ((certs != NULL) && !context->set_cert_authorities(certs)) {
|
| - CFRelease(certs);
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "setClientAuthoritiesBytes has already been called "
|
| - "on the given context."));
|
| - }
|
| -
|
| - CheckStatus(status, "TlsException", "Failure in setClientAuthoritiesBytes");
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "SecurityContext.setClientAuthoritiesBytes is not yet implemented."));
|
| }
|
|
|
|
|
| @@ -998,128 +426,27 @@ void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
|
| }
|
|
|
|
|
| -static char* GetNameFromCert(SecCertificateRef certificate,
|
| - CFTypeRef field,
|
| - CFStringRef name) {
|
| - char* issuer_name = NULL;
|
| -
|
| - CFTypeRef keys[] = { field };
|
| - CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
|
| - CFErrorRef error = NULL;
|
| - CFDictionaryRef cert_dict =
|
| - SecCertificateCopyValues(certificate, key_array, &error);
|
| - if (cert_dict == NULL) {
|
| - CFRelease(key_array);
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "X509.issuer failed to copy issuer field out of certificate"));
|
| - }
|
| -
|
| - CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
|
| - ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
|
| - CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
|
| -
|
| - item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
|
| - ASSERT(CFGetTypeID(item) == CFArrayGetTypeID());
|
| - CFArrayRef val_array = reinterpret_cast<CFArrayRef>(item);
|
| -
|
| - for (intptr_t i = 0; i < CFArrayGetCount(val_array); i++) {
|
| - item = CFArrayGetValueAtIndex(val_array, i);
|
| - ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
|
| - CFDictionaryRef val_dict2 = reinterpret_cast<CFDictionaryRef>(item);
|
| -
|
| - item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyLabel);
|
| - ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
|
| - CFStringRef label = reinterpret_cast<CFStringRef>(item);
|
| -
|
| - if (CFStringCompare(label, name, 0) == kCFCompareEqualTo) {
|
| - item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyValue);
|
| - ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
|
| - CFStringRef value = reinterpret_cast<CFStringRef>(item);
|
| - issuer_name = CFStringRefToCString(value);
|
| - break;
|
| - }
|
| - }
|
| -
|
| - CFRelease(cert_dict);
|
| - CFRelease(key_array);
|
| - return issuer_name;
|
| -}
|
| -
|
| -
|
| void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
|
| - SecCertificateRef certificate = GetX509Certificate(args);
|
| - char* subject_name = GetNameFromCert(
|
| - certificate,
|
| - kSecOIDX509V1SubjectName,
|
| - reinterpret_cast<CFStringRef>(kSecOIDCommonName));
|
| - if (subject_name == NULL) {
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "X509.subject failed to find issuer's common name."));
|
| - } else {
|
| - Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_name));
|
| - }
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "X509Certificate.subject is not yet implemented."));
|
| }
|
|
|
|
|
| void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) {
|
| - SecCertificateRef certificate = GetX509Certificate(args);
|
| - char* issuer_name = GetNameFromCert(
|
| - certificate,
|
| - kSecOIDX509V1IssuerName,
|
| - reinterpret_cast<CFStringRef>(kSecOIDCommonName));
|
| - if (issuer_name == NULL) {
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "X509.issuer failed to find issuer's common name."));
|
| - } else {
|
| - Dart_SetReturnValue(args, Dart_NewStringFromCString(issuer_name));
|
| - }
|
| -}
|
| -
|
| -
|
| -// Returns the number of seconds since the epoch from 'field'.
|
| -static int64_t GetTimeFromCert(SecCertificateRef certificate, CFTypeRef field) {
|
| - CFTypeRef keys[] = { field };
|
| - CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
|
| - CFErrorRef error = NULL;
|
| - CFDictionaryRef cert_dict =
|
| - SecCertificateCopyValues(certificate, key_array, &error);
|
| - if (cert_dict == NULL) {
|
| - CFRelease(key_array);
|
| - Dart_ThrowException(DartUtils::NewDartArgumentError(
|
| - "X509.startValidity: failed to copy issuer field out of certificate"));
|
| - }
|
| -
|
| - CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
|
| - ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
|
| - CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
|
| -
|
| - item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
|
| - ASSERT(CFGetTypeID(item) == CFNumberGetTypeID());
|
| - CFNumberRef date_number = reinterpret_cast<CFNumberRef>(item);
|
| -
|
| - CFAbsoluteTime date_abs_time;
|
| - CFNumberGetValue(date_number, kCFNumberDoubleType, &date_abs_time);
|
| - CFAbsoluteTime seconds_since_epoch =
|
| - date_abs_time + kCFAbsoluteTimeIntervalSince1970;
|
| - return static_cast<int64_t>(seconds_since_epoch) * 1000LL;
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "X509Certificate.issuer is not supported on this platform."));
|
| }
|
|
|
|
|
| void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) {
|
| - SecCertificateRef certificate = GetX509Certificate(args);
|
| - int64_t seconds_since_epoch = GetTimeFromCert(certificate,
|
| - kSecOIDX509V1ValidityNotBefore);
|
| - Dart_SetReturnValue(args,
|
| - Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "X509Certificate.startValidity is not supported on this platform."));
|
| }
|
|
|
|
|
| void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) {
|
| - SecCertificateRef certificate = GetX509Certificate(args);
|
| - int64_t seconds_since_epoch = GetTimeFromCert(certificate,
|
| - kSecOIDX509V1ValidityNotAfter);
|
| - Dart_SetReturnValue(args,
|
| - Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
|
| + Dart_ThrowException(DartUtils::NewDartUnsupportedError(
|
| + "X509Certificate.endValidity is not supported on this platform."));
|
| }
|
|
|
|
|
| @@ -1164,16 +491,8 @@ CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
|
| return result;
|
| } else {
|
| TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
|
| - CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
|
| - if (error_string == NULL) {
|
| - status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
|
| - static_cast<intptr_t>(status));
|
| - } else {
|
| - char* error = CFStringRefToCString(error_string);
|
| - status_message.Printf("OSStatus = %ld: %s",
|
| - static_cast<intptr_t>(status), error);
|
| - CFRelease(error_string);
|
| - }
|
| + status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
|
| + static_cast<intptr_t>(status));
|
| CObjectArray* result = new CObjectArray(CObject::NewArray(2));
|
| result->SetAt(0, new CObjectInt32(CObject::NewInt32(status)));
|
| result->SetAt(1, new CObjectString(CObject::NewString(
|
| @@ -1519,38 +838,6 @@ void SSLFilter::Connect(Dart_Handle dart_this,
|
| "TlsException",
|
| "Failed to set minimum protocol version to kTLSProtocol1");
|
|
|
| - // If the context has a private key and certificate chain, combine the
|
| - // private key and first certificate into a SecIdentityRef, and place that
|
| - // and the remaining certs in an array to pass to SSLSetCertificate().
|
| - if ((context->private_key() != NULL) && (context->cert_chain() != NULL)) {
|
| - CFIndex chain_length = CFArrayGetCount(context->cert_chain());
|
| - CFMutableArrayRef certs =
|
| - CFArrayCreateMutable(NULL, chain_length, &kCFTypeArrayCallBacks);
|
| - CFTypeRef item = CFArrayGetValueAtIndex(context->cert_chain(), 0);
|
| - ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
|
| - SecCertificateRef first_cert =
|
| - reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
|
| - SecIdentityRef identity =
|
| - SecIdentityCreate(NULL, first_cert, context->private_key());
|
| - CFArrayAppendValue(certs, identity);
|
| - for (CFIndex i = 0; i < chain_length; i++) {
|
| - CFArrayAppendValue(certs,
|
| - CFArrayGetValueAtIndex(context->cert_chain(), i));
|
| - }
|
| - CFRelease(identity);
|
| - status = SSLSetCertificate(ssl_context, certs);
|
| - CFRelease(certs);
|
| - CheckStatus(status, "TlsException", "SSLSetCertificate failed");
|
| - }
|
| -
|
| - if (context->cert_authorities() != NULL) {
|
| - status = SSLSetCertificateAuthorities(
|
| - ssl_context, context->cert_authorities(), true);
|
| - CheckStatus(status,
|
| - "TlsException",
|
| - "Failed to set certificate authorities");
|
| - }
|
| -
|
| if (is_server) {
|
| SSLAuthenticate auth =
|
| require_client_certificate
|
| @@ -1611,12 +898,8 @@ OSStatus SSLFilter::EvaluatePeerTrust() {
|
| return status;
|
| }
|
|
|
| - CFArrayRef trusted_certs = NULL;
|
| - if (cert_context_->trusted_certs() != NULL) {
|
| - trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs());
|
| - } else {
|
| - trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
|
| - }
|
| + CFArrayRef trusted_certs =
|
| + CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
|
|
|
| status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs);
|
| if (status != noErr) {
|
| @@ -2022,7 +1305,6 @@ OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start,
|
| } // namespace bin
|
| } // namespace dart
|
|
|
| -#endif // defined(TARGET_OS_MACOS)
|
| +#endif // TARGET_OS_IOS
|
|
|
| -#endif // !defined(DART_IO_DISABLED) &&
|
| - // !defined(DART_IO_SECURE_SOCKET_DISABLED)
|
| +#endif // !defined(DART_IO_SECURE_SOCKET_DISABLED)
|
|
|