| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED) | 5 #if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if TARGET_OS_IOS | 8 #if TARGET_OS_IOS |
| 9 | 9 |
| 10 #include "bin/secure_socket.h" | 10 #include "bin/secure_socket.h" |
| 11 #include "bin/secure_socket_macos.h" | 11 #include "bin/secure_socket_ios.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> |
| 19 | 19 |
| 20 #include <CoreFoundation/CoreFoundation.h> | 20 #include <CoreFoundation/CoreFoundation.h> |
| 21 #include <Security/SecureTransport.h> | 21 #include <Security/SecureTransport.h> |
| (...skipping 23 matching lines...) Expand all Loading... |
| 45 | 45 |
| 46 namespace dart { | 46 namespace dart { |
| 47 namespace bin { | 47 namespace bin { |
| 48 | 48 |
| 49 static const int kSSLFilterNativeFieldIndex = 0; | 49 static const int kSSLFilterNativeFieldIndex = 0; |
| 50 static const int kSecurityContextNativeFieldIndex = 0; | 50 static const int kSecurityContextNativeFieldIndex = 0; |
| 51 static const int kX509NativeFieldIndex = 0; | 51 static const int kX509NativeFieldIndex = 0; |
| 52 | 52 |
| 53 static const bool SSL_LOG_STATUS = false; | 53 static const bool SSL_LOG_STATUS = false; |
| 54 static const bool SSL_LOG_DATA = false; | 54 static const bool SSL_LOG_DATA = false; |
| 55 static const bool SSL_LOG_CERTS = false; |
| 55 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; | 56 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; |
| 57 static const intptr_t PEM_BUFSIZE = 1024; |
| 56 | 58 |
| 57 // SSLCertContext wraps the certificates needed for a SecureTransport | 59 static char* CFStringRefToCString(CFStringRef cfstring) { |
| 58 // connection. Fields are protected by the mutex_ field, and may only be set | 60 CFIndex len = CFStringGetLength(cfstring); |
| 59 // once. This is to allow access by both the Dart thread and the IOService | 61 CFIndex max_len = |
| 60 // thread. Setters return false if the field was already set. | 62 CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1; |
| 61 class SSLCertContext { | 63 char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(max_len)); |
| 62 public: | 64 ASSERT(result != NULL); |
| 63 SSLCertContext() : | 65 bool success = |
| 64 mutex_(new Mutex()), | 66 CFStringGetCString(cfstring, result, max_len, kCFStringEncodingUTF8); |
| 65 trusted_certs_(NULL), | 67 return success ? result : NULL; |
| 66 trust_builtin_(false) {} | 68 } |
| 67 | 69 |
| 68 ~SSLCertContext() { | |
| 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. | |
| 87 } | |
| 88 | |
| 89 bool trust_builtin() { | |
| 90 MutexLocker m(mutex_); | |
| 91 return trust_builtin_; | |
| 92 } | |
| 93 void set_trust_builtin(bool trust_builtin) { | |
| 94 MutexLocker m(mutex_); | |
| 95 trust_builtin_ = trust_builtin; | |
| 96 } | |
| 97 | |
| 98 private: | |
| 99 // The context is accessed both by Dart code and the IOService. This mutex | |
| 100 // protects all fields. | |
| 101 Mutex* mutex_; | |
| 102 CFMutableArrayRef trusted_certs_; | |
| 103 bool trust_builtin_; | |
| 104 | |
| 105 DISALLOW_COPY_AND_ASSIGN(SSLCertContext); | |
| 106 }; | |
| 107 | 70 |
| 108 // Handle an error reported from the SecureTransport library. | 71 // Handle an error reported from the SecureTransport library. |
| 109 static void ThrowIOException(OSStatus status, | 72 static void ThrowIOException(OSStatus status, |
| 110 const char* exception_type, | 73 const char* exception_type, |
| 111 const char* message) { | 74 const char* message) { |
| 112 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); | 75 TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE); |
| 113 status_message.Printf("OSStatus = %ld: https://www.osstatus.com", | 76 status_message.Printf("OSStatus = %ld: https://www.osstatus.com", |
| 114 static_cast<intptr_t>(status)); | 77 static_cast<intptr_t>(status)); |
| 115 OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL); | 78 OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL); |
| 116 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); | 79 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 141 kSSLFilterNativeFieldIndex, | 104 kSSLFilterNativeFieldIndex, |
| 142 reinterpret_cast<intptr_t*>(&filter))); | 105 reinterpret_cast<intptr_t*>(&filter))); |
| 143 return filter; | 106 return filter; |
| 144 } | 107 } |
| 145 | 108 |
| 146 | 109 |
| 147 static void DeleteFilter(void* isolate_data, | 110 static void DeleteFilter(void* isolate_data, |
| 148 Dart_WeakPersistentHandle handle, | 111 Dart_WeakPersistentHandle handle, |
| 149 void* context_pointer) { | 112 void* context_pointer) { |
| 150 SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer); | 113 SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer); |
| 151 delete filter; | 114 filter->Release(); |
| 152 } | 115 } |
| 153 | 116 |
| 154 | 117 |
| 155 static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) { | 118 static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) { |
| 156 ASSERT(filter != NULL); | 119 ASSERT(filter != NULL); |
| 157 const int approximate_size_of_filter = 1500; | 120 const int approximate_size_of_filter = 1500; |
| 158 Dart_Handle dart_this = Dart_GetNativeArgument(args, 0); | 121 Dart_Handle dart_this = Dart_GetNativeArgument(args, 0); |
| 159 RETURN_IF_ERROR(dart_this); | 122 RETURN_IF_ERROR(dart_this); |
| 160 ASSERT(Dart_IsInstance(dart_this)); | 123 ASSERT(Dart_IsInstance(dart_this)); |
| 161 Dart_Handle err = Dart_SetNativeInstanceField( | 124 Dart_Handle err = Dart_SetNativeInstanceField( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 180 kSecurityContextNativeFieldIndex, | 143 kSecurityContextNativeFieldIndex, |
| 181 reinterpret_cast<intptr_t*>(&context))); | 144 reinterpret_cast<intptr_t*>(&context))); |
| 182 return context; | 145 return context; |
| 183 } | 146 } |
| 184 | 147 |
| 185 | 148 |
| 186 static void DeleteCertContext(void* isolate_data, | 149 static void DeleteCertContext(void* isolate_data, |
| 187 Dart_WeakPersistentHandle handle, | 150 Dart_WeakPersistentHandle handle, |
| 188 void* context_pointer) { | 151 void* context_pointer) { |
| 189 SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer); | 152 SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer); |
| 190 delete context; | 153 context->Release(); |
| 191 } | 154 } |
| 192 | 155 |
| 193 | 156 |
| 194 static Dart_Handle SetSecurityContext(Dart_NativeArguments args, | 157 static Dart_Handle SetSecurityContext(Dart_NativeArguments args, |
| 195 SSLCertContext* context) { | 158 SSLCertContext* context) { |
| 196 const int approximate_size_of_context = 1500; | 159 const int approximate_size_of_context = 1500; |
| 197 Dart_Handle dart_this = Dart_GetNativeArgument(args, 0); | 160 Dart_Handle dart_this = Dart_GetNativeArgument(args, 0); |
| 198 RETURN_IF_ERROR(dart_this); | 161 RETURN_IF_ERROR(dart_this); |
| 199 ASSERT(Dart_IsInstance(dart_this)); | 162 ASSERT(Dart_IsInstance(dart_this)); |
| 200 Dart_Handle err = Dart_SetNativeInstanceField( | 163 Dart_Handle err = Dart_SetNativeInstanceField( |
| 201 dart_this, | 164 dart_this, |
| 202 kSecurityContextNativeFieldIndex, | 165 kSecurityContextNativeFieldIndex, |
| 203 reinterpret_cast<intptr_t>(context)); | 166 reinterpret_cast<intptr_t>(context)); |
| 204 RETURN_IF_ERROR(err); | 167 RETURN_IF_ERROR(err); |
| 205 Dart_NewWeakPersistentHandle(dart_this, | 168 Dart_NewWeakPersistentHandle(dart_this, |
| 206 context, | 169 context, |
| 207 approximate_size_of_context, | 170 approximate_size_of_context, |
| 208 DeleteCertContext); | 171 DeleteCertContext); |
| 209 return Dart_Null(); | 172 return Dart_Null(); |
| 210 } | 173 } |
| 211 | 174 |
| 212 | 175 |
| 176 static SecCertificateRef GetX509Certificate(Dart_NativeArguments args) { |
| 177 SecCertificateRef certificate; |
| 178 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 179 ASSERT(Dart_IsInstance(dart_this)); |
| 180 ThrowIfError(Dart_GetNativeInstanceField( |
| 181 dart_this, |
| 182 kX509NativeFieldIndex, |
| 183 reinterpret_cast<intptr_t*>(&certificate))); |
| 184 return certificate; |
| 185 } |
| 186 |
| 187 |
| 213 static void ReleaseCertificate(void* isolate_data, | 188 static void ReleaseCertificate(void* isolate_data, |
| 214 Dart_WeakPersistentHandle handle, | 189 Dart_WeakPersistentHandle handle, |
| 215 void* context_pointer) { | 190 void* context_pointer) { |
| 216 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer); | 191 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer); |
| 217 CFRelease(cert); | 192 CFRelease(cert); |
| 218 } | 193 } |
| 219 | 194 |
| 220 | 195 |
| 221 static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) { | 196 static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) { |
| 222 const intptr_t approximate_size_of_certificate = 1500; | 197 const intptr_t approximate_size_of_certificate = 1500; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 249 result, | 224 result, |
| 250 kX509NativeFieldIndex, | 225 kX509NativeFieldIndex, |
| 251 reinterpret_cast<intptr_t>(certificate)); | 226 reinterpret_cast<intptr_t>(certificate)); |
| 252 if (Dart_IsError(status)) { | 227 if (Dart_IsError(status)) { |
| 253 return status; | 228 return status; |
| 254 } | 229 } |
| 255 return result; | 230 return result; |
| 256 } | 231 } |
| 257 | 232 |
| 258 | 233 |
| 234 static const char* GetPasswordArgument(Dart_NativeArguments args, |
| 235 intptr_t index) { |
| 236 Dart_Handle password_object = |
| 237 ThrowIfError(Dart_GetNativeArgument(args, index)); |
| 238 const char* password = NULL; |
| 239 if (Dart_IsString(password_object)) { |
| 240 ThrowIfError(Dart_StringToCString(password_object, &password)); |
| 241 if (strlen(password) > PEM_BUFSIZE - 1) { |
| 242 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 243 "Password length is greater than 1023 bytes.")); |
| 244 } |
| 245 } else if (Dart_IsNull(password_object)) { |
| 246 password = ""; |
| 247 } else { |
| 248 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 249 "Password is not a String or null")); |
| 250 } |
| 251 return password; |
| 252 } |
| 253 |
| 254 |
| 255 static OSStatus TryPKCS12Import(CFDataRef cfdata, |
| 256 CFStringRef password, |
| 257 CFArrayRef* out_certs, |
| 258 SecIdentityRef* out_identity) { |
| 259 const void* keys[] = { kSecImportExportPassphrase }; |
| 260 const void* values[] = { password }; |
| 261 CFDictionaryRef params = |
| 262 CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); |
| 263 CFArrayRef items = NULL; |
| 264 OSStatus status = SecPKCS12Import(cfdata, params, &items); |
| 265 CFRelease(params); |
| 266 |
| 267 if (status != noErr) { |
| 268 if (SSL_LOG_STATUS) { |
| 269 Log::PrintErr("SecPKCS12Import: status = %ld", |
| 270 static_cast<intptr_t>(status)); |
| 271 return status; |
| 272 } |
| 273 } |
| 274 |
| 275 CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items); |
| 276 if (SSL_LOG_CERTS) { |
| 277 Log::PrintErr("TryPKCS12Import succeeded, count = %ld\n", items_length); |
| 278 } |
| 279 |
| 280 // Empty list indicates a decoding failure of some sort. |
| 281 if ((items != NULL) && (items_length == 0)) { |
| 282 CFRelease(items); |
| 283 return errSSLBadCert; |
| 284 } |
| 285 |
| 286 CFMutableArrayRef result_certs = |
| 287 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
| 288 SecIdentityRef result_identity = NULL; |
| 289 |
| 290 for (CFIndex i = 0; i < items_length; i++) { |
| 291 CFTypeRef item = |
| 292 reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i)); |
| 293 ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID()); |
| 294 CFDictionaryRef dict = reinterpret_cast<CFDictionaryRef>(item); |
| 295 |
| 296 // Trust. |
| 297 CFTypeRef trust_item = CFDictionaryGetValue(dict, kSecImportItemTrust); |
| 298 if (trust_item != NULL) { |
| 299 ASSERT(CFGetTypeID(trust_item) == SecTrustGetTypeID()); |
| 300 if (SSL_LOG_CERTS) { |
| 301 Log::PrintErr("\titem %ld has a trust object\n", i); |
| 302 } |
| 303 // TODO(zra): Is this useful for anything? |
| 304 } |
| 305 |
| 306 // Identity. |
| 307 CFTypeRef identity_item = |
| 308 CFDictionaryGetValue(dict, kSecImportItemIdentity); |
| 309 if (identity_item != NULL) { |
| 310 ASSERT(CFGetTypeID(identity_item) == SecIdentityGetTypeID()); |
| 311 if (SSL_LOG_CERTS) { |
| 312 Log::PrintErr("\titem %ld has an identity object\n", i); |
| 313 } |
| 314 // Only extract the first identity we find. |
| 315 if (result_identity == NULL) { |
| 316 result_identity = |
| 317 reinterpret_cast<SecIdentityRef>(const_cast<void*>(identity_item)); |
| 318 CFRetain(result_identity); |
| 319 } |
| 320 } |
| 321 |
| 322 // Certificates. |
| 323 CFTypeRef cert_items = CFDictionaryGetValue(dict, kSecImportItemCertChain); |
| 324 if (cert_items != NULL) { |
| 325 ASSERT(CFGetTypeID(cert_items) == CFArrayGetTypeID()); |
| 326 CFArrayRef certs = reinterpret_cast<CFArrayRef>(cert_items); |
| 327 if (SSL_LOG_CERTS) { |
| 328 CFIndex count = CFArrayGetCount(certs); |
| 329 Log::PrintErr("\titem %ld has a cert chain %ld certs long\n", i, count); |
| 330 } |
| 331 CFArrayAppendArray( |
| 332 result_certs, certs, CFRangeMake(0, CFArrayGetCount(certs))); |
| 333 } |
| 334 } |
| 335 |
| 336 if (out_certs == NULL) { |
| 337 if (result_certs != NULL) { |
| 338 CFRelease(result_certs); |
| 339 } |
| 340 } else { |
| 341 *out_certs = result_certs; |
| 342 } |
| 343 |
| 344 if (out_identity == NULL) { |
| 345 if (result_identity != NULL) { |
| 346 CFRelease(result_identity); |
| 347 } |
| 348 } else { |
| 349 *out_identity = result_identity; |
| 350 } |
| 351 |
| 352 // On failure, don't return any objects. |
| 353 ASSERT((status == noErr) || |
| 354 ((result_certs == NULL) && (result_identity == NULL))); |
| 355 return status; |
| 356 } |
| 357 |
| 358 |
| 359 static OSStatus ExtractSecItems(uint8_t* buffer, |
| 360 intptr_t length, |
| 361 const char* password, |
| 362 CFArrayRef* out_certs, |
| 363 SecIdentityRef* out_identity) { |
| 364 ASSERT(buffer != NULL); |
| 365 ASSERT(password != NULL); |
| 366 OSStatus status = noErr; |
| 367 |
| 368 CFDataRef cfdata = CFDataCreateWithBytesNoCopy( |
| 369 NULL, buffer, length, kCFAllocatorNull); |
| 370 CFStringRef cfpassword = CFStringCreateWithCStringNoCopy( |
| 371 NULL, password, kCFStringEncodingUTF8, kCFAllocatorNull); |
| 372 ASSERT(cfdata != NULL); |
| 373 ASSERT(cfpassword != NULL); |
| 374 |
| 375 status = TryPKCS12Import(cfdata, cfpassword, out_certs, out_identity); |
| 376 |
| 377 CFRelease(cfdata); |
| 378 CFRelease(cfpassword); |
| 379 return status; |
| 380 } |
| 381 |
| 382 |
| 259 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { | 383 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { |
| 260 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | 384 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 261 SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer. | 385 SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer. |
| 386 filter->Retain(); |
| 262 Dart_Handle err = SetFilter(args, filter); | 387 Dart_Handle err = SetFilter(args, filter); |
| 263 if (Dart_IsError(err)) { | 388 if (Dart_IsError(err)) { |
| 264 delete filter; | 389 filter->Release(); |
| 265 Dart_PropagateError(err); | 390 Dart_PropagateError(err); |
| 266 } | 391 } |
| 267 err = filter->Init(dart_this); | 392 err = filter->Init(dart_this); |
| 268 if (Dart_IsError(err)) { | 393 if (Dart_IsError(err)) { |
| 269 // The finalizer was set up by SetFilter. It will delete `filter` if there | 394 // The finalizer was set up by SetFilter. It will delete `filter` if there |
| 270 // is an error. | 395 // is an error. |
| 271 filter->Destroy(); | 396 filter->Destroy(); |
| 272 Dart_PropagateError(err); | 397 Dart_PropagateError(err); |
| 273 } | 398 } |
| 274 } | 399 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 GetFilter(args)->RegisterBadCertificateCallback(callback); | 490 GetFilter(args)->RegisterBadCertificateCallback(callback); |
| 366 } | 491 } |
| 367 | 492 |
| 368 | 493 |
| 369 void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) { | 494 void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) { |
| 370 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); | 495 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); |
| 371 } | 496 } |
| 372 | 497 |
| 373 | 498 |
| 374 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { | 499 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { |
| 375 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); | 500 SSLFilter* filter = GetFilter(args); |
| 501 // This filter pointer is passed to the IO Service thread. The IO Service |
| 502 // thread must Release() the pointer when it is done with it. |
| 503 filter->Retain(); |
| 504 intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter); |
| 376 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); | 505 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); |
| 377 } | 506 } |
| 378 | 507 |
| 379 | 508 |
| 380 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { | 509 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { |
| 381 SSLCertContext* cert_context = new SSLCertContext(); | 510 SSLCertContext* cert_context = new SSLCertContext(); |
| 511 cert_context->Retain(); |
| 382 // cert_context deleted in DeleteCertContext finalizer. | 512 // cert_context deleted in DeleteCertContext finalizer. |
| 383 Dart_Handle err = SetSecurityContext(args, cert_context); | 513 Dart_Handle err = SetSecurityContext(args, cert_context); |
| 384 if (Dart_IsError(err)) { | 514 if (Dart_IsError(err)) { |
| 385 delete cert_context; | 515 cert_context->Release(); |
| 386 Dart_PropagateError(err); | 516 Dart_PropagateError(err); |
| 387 } | 517 } |
| 388 } | 518 } |
| 389 | 519 |
| 390 | 520 |
| 391 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 521 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
| 392 Dart_NativeArguments args) { | 522 Dart_NativeArguments args) { |
| 393 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 523 SSLCertContext* context = GetSecurityContext(args); |
| 394 "SecurityContext.usePrivateKeyBytes is not yet implemented.")); | 524 const char* password = GetPasswordArgument(args, 2); |
| 525 |
| 526 OSStatus status; |
| 527 CFArrayRef cert_chain = NULL; |
| 528 SecIdentityRef identity = NULL; |
| 529 { |
| 530 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 531 status = ExtractSecItems( |
| 532 buffer.get(), buffer.length(), password, &cert_chain, &identity); |
| 533 } |
| 534 |
| 535 // Set the context fields. Repeated calls to usePrivateKeyBytes are an error. |
| 536 bool set_failure = false; |
| 537 if ((identity != NULL) && !context->set_identity(identity)) { |
| 538 CFRelease(identity); |
| 539 if (cert_chain != NULL) { |
| 540 CFRelease(cert_chain); |
| 541 } |
| 542 set_failure = true; |
| 543 } |
| 544 |
| 545 // We can't have set a cert_chain without also having set an identity. |
| 546 // That is, if context->set_identity() succeeds, then it is impossible for |
| 547 // context->set_cert_chain() to fail. This is because SecPKCS12Import never |
| 548 // returns a cert chain without also returning a private key. |
| 549 ASSERT(set_failure || (context->cert_chain() == NULL)); |
| 550 if (!set_failure && (cert_chain != NULL)) { |
| 551 context->set_cert_chain(cert_chain); |
| 552 } |
| 553 |
| 554 if (set_failure) { |
| 555 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 556 "usePrivateKeyBytes has already been called on the given context.")); |
| 557 } |
| 558 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); |
| 395 } | 559 } |
| 396 | 560 |
| 397 | 561 |
| 398 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 562 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
| 399 Dart_NativeArguments args) { | 563 Dart_NativeArguments args) { |
| 400 SSLCertContext* context = GetSecurityContext(args); | 564 SSLCertContext* context = GetSecurityContext(args); |
| 401 | 565 |
| 402 OSStatus status = noErr; | 566 OSStatus status = noErr; |
| 403 SecCertificateRef cert = NULL; | 567 SecCertificateRef cert = NULL; |
| 404 { | 568 { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 426 | 590 |
| 427 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 591 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
| 428 Dart_NativeArguments args) { | 592 Dart_NativeArguments args) { |
| 429 SSLCertContext* context = GetSecurityContext(args); | 593 SSLCertContext* context = GetSecurityContext(args); |
| 430 context->set_trust_builtin(true); | 594 context->set_trust_builtin(true); |
| 431 } | 595 } |
| 432 | 596 |
| 433 | 597 |
| 434 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 598 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
| 435 Dart_NativeArguments args) { | 599 Dart_NativeArguments args) { |
| 436 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 600 // This is a no-op on iOS. We get the cert chain along with the private key |
| 437 "SecurityContext.useCertificateChainBytes is not yet implemented.")); | 601 // in UsePrivateyKeyBytes(). |
| 438 } | 602 } |
| 439 | 603 |
| 440 | 604 |
| 441 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 605 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
| 442 Dart_NativeArguments args) { | 606 Dart_NativeArguments args) { |
| 443 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 607 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
| 444 "SecurityContext.setClientAuthoritiesBytes is not yet implemented.")); | 608 "SecurityContext.setClientAuthoritiesBytes is not supported on this " |
| 609 "platform.")); |
| 445 } | 610 } |
| 446 | 611 |
| 447 | 612 |
| 448 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( | 613 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( |
| 449 Dart_NativeArguments args) { | 614 Dart_NativeArguments args) { |
| 450 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 615 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
| 451 "ALPN is not supported on this platform")); | 616 "ALPN is not supported on this platform")); |
| 452 } | 617 } |
| 453 | 618 |
| 454 | 619 |
| 455 void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) { | 620 void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) { |
| 456 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 621 SecCertificateRef certificate = GetX509Certificate(args); |
| 457 "X509Certificate.subject is not yet implemented.")); | 622 CFStringRef cfsubject = SecCertificateCopySubjectSummary(certificate); |
| 623 if (cfsubject != NULL) { |
| 624 char* csubject = CFStringRefToCString(cfsubject); |
| 625 CFRelease(cfsubject); |
| 626 Dart_SetReturnValue(args, Dart_NewStringFromCString(csubject)); |
| 627 } else { |
| 628 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 629 "X509.subject failed to find subject's common name.")); |
| 630 } |
| 458 } | 631 } |
| 459 | 632 |
| 460 | 633 |
| 461 void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) { | 634 void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) { |
| 462 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 635 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
| 463 "X509Certificate.issuer is not supported on this platform.")); | 636 "X509Certificate.issuer is not supported on this platform.")); |
| 464 } | 637 } |
| 465 | 638 |
| 466 | 639 |
| 467 void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) { | 640 void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 491 // end for output buffers. Therefore, the Dart thread can simultaneously | 664 // end for output buffers. Therefore, the Dart thread can simultaneously |
| 492 // write to the free space and end pointer of input buffers, and read from | 665 // write to the free space and end pointer of input buffers, and read from |
| 493 // the data space of output buffers, and modify the start pointer. | 666 // the data space of output buffers, and modify the start pointer. |
| 494 // | 667 // |
| 495 // When ProcessFilter returns, the Dart thread is responsible for combining | 668 // When ProcessFilter returns, the Dart thread is responsible for combining |
| 496 // the updated pointers from Dart and C++, to make the new valid state of | 669 // the updated pointers from Dart and C++, to make the new valid state of |
| 497 // the circular buffer. | 670 // the circular buffer. |
| 498 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) { | 671 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) { |
| 499 CObjectIntptr filter_object(request[0]); | 672 CObjectIntptr filter_object(request[0]); |
| 500 SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value()); | 673 SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value()); |
| 674 RefCntReleaseScope<SSLFilter> rs(filter); |
| 675 |
| 501 bool in_handshake = CObjectBool(request[1]).Value(); | 676 bool in_handshake = CObjectBool(request[1]).Value(); |
| 502 intptr_t starts[SSLFilter::kNumBuffers]; | 677 intptr_t starts[SSLFilter::kNumBuffers]; |
| 503 intptr_t ends[SSLFilter::kNumBuffers]; | 678 intptr_t ends[SSLFilter::kNumBuffers]; |
| 504 for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) { | 679 for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) { |
| 505 starts[i] = CObjectInt32(request[2 * i + 2]).Value(); | 680 starts[i] = CObjectInt32(request[2 * i + 2]).Value(); |
| 506 ends[i] = CObjectInt32(request[2 * i + 3]).Value(); | 681 ends[i] = CObjectInt32(request[2 * i + 3]).Value(); |
| 507 } | 682 } |
| 508 | 683 |
| 509 OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake); | 684 OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake); |
| 510 if (status == noErr) { | 685 if (status == noErr) { |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 ssl_context, kSSLSessionOptionBreakOnServerAuth, true); | 1032 ssl_context, kSSLSessionOptionBreakOnServerAuth, true); |
| 858 CheckStatus(status, | 1033 CheckStatus(status, |
| 859 "TlsException", | 1034 "TlsException", |
| 860 "Failed to set BreakOnServerAuth option"); | 1035 "Failed to set BreakOnServerAuth option"); |
| 861 | 1036 |
| 862 status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1); | 1037 status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1); |
| 863 CheckStatus(status, | 1038 CheckStatus(status, |
| 864 "TlsException", | 1039 "TlsException", |
| 865 "Failed to set minimum protocol version to kTLSProtocol1"); | 1040 "Failed to set minimum protocol version to kTLSProtocol1"); |
| 866 | 1041 |
| 1042 // If the context has an identity pass it to SSLSetCertificate(). |
| 1043 if (context->identity() != NULL) { |
| 1044 CFMutableArrayRef chain = |
| 1045 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
| 1046 CFArrayAppendValue(chain, context->identity()); |
| 1047 |
| 1048 // Append the certificate chain if there is one. |
| 1049 if (context->cert_chain() != NULL) { |
| 1050 // Skip the first one, it's already included in the identity. |
| 1051 CFIndex chain_length = CFArrayGetCount(context->cert_chain()); |
| 1052 if (chain_length > 1) { |
| 1053 CFArrayAppendArray( |
| 1054 chain, context->cert_chain(), CFRangeMake(1, chain_length)); |
| 1055 } |
| 1056 } |
| 1057 |
| 1058 status = SSLSetCertificate(ssl_context, chain); |
| 1059 CFRelease(chain); |
| 1060 CheckStatus(status, "TlsException", "SSLSetCertificate failed"); |
| 1061 } |
| 1062 |
| 867 if (is_server) { | 1063 if (is_server) { |
| 868 SSLAuthenticate auth = | 1064 SSLAuthenticate auth = |
| 869 require_client_certificate | 1065 require_client_certificate |
| 870 ? kAlwaysAuthenticate | 1066 ? kAlwaysAuthenticate |
| 871 : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate); | 1067 : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate); |
| 872 status = SSLSetClientSideAuthenticate(ssl_context, auth); | 1068 status = SSLSetClientSideAuthenticate(ssl_context, auth); |
| 873 CheckStatus(status, | 1069 CheckStatus(status, |
| 874 "TlsException", | 1070 "TlsException", |
| 875 "Failed to set client authentication mode"); | 1071 "Failed to set client authentication mode"); |
| 876 | 1072 |
| 877 // If we're at least trying client authentication, then break handshake | 1073 // If we're at least trying client authentication, then break handshake |
| 878 // for client authentication. | 1074 // for client authentication. |
| 879 if (auth != kNeverAuthenticate) { | 1075 if (auth != kNeverAuthenticate) { |
| 880 status = SSLSetSessionOption( | 1076 status = SSLSetSessionOption( |
| 881 ssl_context, kSSLSessionOptionBreakOnClientAuth, true); | 1077 ssl_context, kSSLSessionOptionBreakOnClientAuth, true); |
| 882 CheckStatus(status, | 1078 CheckStatus(status, |
| 883 "TlsException", | 1079 "TlsException", |
| 884 "Failed to set client authentication mode"); | 1080 "Failed to set client authentication mode"); |
| 885 } | 1081 } |
| 886 } | 1082 } |
| 887 | 1083 |
| 888 // Add the contexts to our wrapper. | 1084 // Add the contexts to our wrapper. |
| 889 cert_context_ = context; | 1085 cert_context_.set(context); |
| 890 ssl_context_ = ssl_context; | 1086 ssl_context_ = ssl_context; |
| 891 is_server_ = is_server; | 1087 is_server_ = is_server; |
| 892 | 1088 |
| 893 // Kick-off the handshake. Expect the handshake to need more data. | 1089 // Kick-off the handshake. Expect the handshake to need more data. |
| 894 // SSLHandshake calls our SSLReadCallback and SSLWriteCallback. | 1090 // SSLHandshake calls our SSLReadCallback and SSLWriteCallback. |
| 895 status = SSLHandshake(ssl_context); | 1091 status = SSLHandshake(ssl_context); |
| 896 ASSERT(status != noErr); | 1092 ASSERT(status != noErr); |
| 897 if (status == errSSLWouldBlock) { | 1093 if (status == errSSLWouldBlock) { |
| 898 status = noErr; | 1094 status = noErr; |
| 899 in_handshake_ = true; | 1095 in_handshake_ = true; |
| 900 } | 1096 } |
| 901 CheckStatus(status, | 1097 CheckStatus(status, |
| 902 "HandshakeException", | 1098 "HandshakeException", |
| 903 is_server_ ? "Handshake error in server" : "Handshake error in client"); | 1099 is_server_ ? "Handshake error in server" : "Handshake error in client"); |
| 904 } | 1100 } |
| 905 | 1101 |
| 906 | 1102 |
| 907 OSStatus SSLFilter::EvaluatePeerTrust() { | 1103 OSStatus SSLFilter::EvaluatePeerTrust() { |
| 908 OSStatus status = noErr; | 1104 OSStatus status = noErr; |
| 909 | 1105 |
| 910 if (SSL_LOG_STATUS) { | 1106 if (SSL_LOG_STATUS) { |
| 911 Log::Print("Handshake evaluating trust.\n"); | 1107 Log::PrintErr("Handshake evaluating trust.\n"); |
| 912 } | 1108 } |
| 913 SecTrustRef peer_trust = NULL; | 1109 SecTrustRef peer_trust = NULL; |
| 914 status = SSLCopyPeerTrust(ssl_context_, &peer_trust); | 1110 status = SSLCopyPeerTrust(ssl_context_, &peer_trust); |
| 915 if (status != noErr) { | 1111 if (status != noErr) { |
| 916 if (is_server_ && (status == errSSLBadCert)) { | 1112 if (is_server_ && (status == errSSLBadCert)) { |
| 917 // A client certificate was requested, but not required, and wasn't sent. | 1113 // A client certificate was requested, but not required, and wasn't sent. |
| 918 return noErr; | 1114 return noErr; |
| 919 } | 1115 } |
| 920 if (SSL_LOG_STATUS) { | 1116 if (SSL_LOG_STATUS) { |
| 921 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", | 1117 Log::PrintErr("Handshake error from SSLCopyPeerTrust(): %ld.\n", |
| 922 static_cast<intptr_t>(status)); | 1118 static_cast<intptr_t>(status)); |
| 923 } | 1119 } |
| 924 return status; | 1120 return status; |
| 925 } | 1121 } |
| 926 | 1122 |
| 927 CFArrayRef trusted_certs = NULL; | 1123 CFArrayRef trusted_certs = NULL; |
| 928 if (cert_context_->trusted_certs() != NULL) { | 1124 if (cert_context_.get()->trusted_certs() != NULL) { |
| 929 trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs()); | 1125 trusted_certs = |
| 1126 CFArrayCreateCopy(NULL, cert_context_.get()->trusted_certs()); |
| 930 } else { | 1127 } else { |
| 931 trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); | 1128 trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); |
| 932 } | 1129 } |
| 933 | 1130 |
| 934 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); | 1131 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); |
| 935 if (status != noErr) { | 1132 if (status != noErr) { |
| 936 if (SSL_LOG_STATUS) { | 1133 if (SSL_LOG_STATUS) { |
| 937 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", | 1134 Log::PrintErr("Handshake error from SecTrustSetAnchorCertificates: %ld\n", |
| 938 static_cast<intptr_t>(status)); | 1135 static_cast<intptr_t>(status)); |
| 939 } | 1136 } |
| 940 CFRelease(trusted_certs); | 1137 CFRelease(trusted_certs); |
| 941 CFRelease(peer_trust); | 1138 CFRelease(peer_trust); |
| 942 return status; | 1139 return status; |
| 943 } | 1140 } |
| 944 | 1141 |
| 945 if (SSL_LOG_STATUS) { | 1142 if (SSL_LOG_STATUS) { |
| 946 Log::Print("Handshake %s built in root certs\n", | 1143 Log::PrintErr("Handshake %s built in root certs\n", |
| 947 cert_context_->trust_builtin() ? "trusting" : "not trusting"); | 1144 cert_context_.get()->trust_builtin() ? "trusting" : "not trusting"); |
| 948 } | 1145 } |
| 949 | 1146 |
| 950 status = SecTrustSetAnchorCertificatesOnly( | 1147 status = SecTrustSetAnchorCertificatesOnly( |
| 951 peer_trust, !cert_context_->trust_builtin()); | 1148 peer_trust, !cert_context_.get()->trust_builtin()); |
| 952 if (status != noErr) { | 1149 if (status != noErr) { |
| 953 CFRelease(trusted_certs); | 1150 CFRelease(trusted_certs); |
| 954 CFRelease(peer_trust); | 1151 CFRelease(peer_trust); |
| 955 return status; | 1152 return status; |
| 956 } | 1153 } |
| 957 | 1154 |
| 958 SecTrustResultType trust_result; | 1155 SecTrustResultType trust_result; |
| 959 status = SecTrustEvaluate(peer_trust, &trust_result); | 1156 status = SecTrustEvaluate(peer_trust, &trust_result); |
| 960 if (status != noErr) { | 1157 if (status != noErr) { |
| 961 CFRelease(trusted_certs); | 1158 CFRelease(trusted_certs); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 975 | 1172 |
| 976 CFRelease(trusted_certs); | 1173 CFRelease(trusted_certs); |
| 977 CFRelease(peer_trust); | 1174 CFRelease(peer_trust); |
| 978 | 1175 |
| 979 if ((trust_result == kSecTrustResultProceed) || | 1176 if ((trust_result == kSecTrustResultProceed) || |
| 980 (trust_result == kSecTrustResultUnspecified)) { | 1177 (trust_result == kSecTrustResultUnspecified)) { |
| 981 // Trusted. | 1178 // Trusted. |
| 982 return noErr; | 1179 return noErr; |
| 983 } else { | 1180 } else { |
| 984 if (SSL_LOG_STATUS) { | 1181 if (SSL_LOG_STATUS) { |
| 985 Log::Print("Trust eval failed: trust_restul = %d\n", trust_result); | 1182 Log::PrintErr("Trust eval failed: trust_result = %d\n", trust_result); |
| 986 } | 1183 } |
| 987 bad_cert_ = true; | 1184 bad_cert_ = true; |
| 988 return errSSLBadCert; | 1185 return errSSLBadCert; |
| 989 } | 1186 } |
| 990 } | 1187 } |
| 991 | 1188 |
| 992 | 1189 |
| 993 OSStatus SSLFilter::Handshake() { | 1190 OSStatus SSLFilter::Handshake() { |
| 994 ASSERT(cert_context_ != NULL); | 1191 ASSERT(cert_context_.get() != NULL); |
| 995 ASSERT(ssl_context_ != NULL); | 1192 ASSERT(ssl_context_ != NULL); |
| 996 // Try and push handshake along. | 1193 // Try and push handshake along. |
| 997 if (SSL_LOG_STATUS) { | 1194 if (SSL_LOG_STATUS) { |
| 998 Log::Print("Doing SSLHandshake\n"); | 1195 Log::PrintErr("Doing SSLHandshake\n"); |
| 999 } | 1196 } |
| 1000 OSStatus status = SSLHandshake(ssl_context_); | 1197 OSStatus status = SSLHandshake(ssl_context_); |
| 1001 if (SSL_LOG_STATUS) { | 1198 if (SSL_LOG_STATUS) { |
| 1002 Log::Print("SSLHandshake returned %ld\n", static_cast<intptr_t>(status)); | 1199 Log::PrintErr("SSLHandshake returned %ld\n", static_cast<intptr_t>(status)); |
| 1003 } | 1200 } |
| 1004 | 1201 |
| 1005 if ((status == errSSLServerAuthCompleted) || | 1202 if ((status == errSSLServerAuthCompleted) || |
| 1006 (status == errSSLClientAuthCompleted)) { | 1203 (status == errSSLClientAuthCompleted)) { |
| 1007 status = EvaluatePeerTrust(); | 1204 status = EvaluatePeerTrust(); |
| 1008 if (status == errSSLBadCert) { | 1205 if (status == errSSLBadCert) { |
| 1009 // Need to invoke the bad certificate callback. | 1206 // Need to invoke the bad certificate callback. |
| 1010 return noErr; | 1207 return noErr; |
| 1011 } else if (status != noErr) { | 1208 } else if (status != noErr) { |
| 1012 return status; | 1209 return status; |
| 1013 } | 1210 } |
| 1014 // When trust evaluation succeeds, we can call SSLHandshake again | 1211 // When trust evaluation succeeds, we can call SSLHandshake again |
| 1015 // immediately. | 1212 // immediately. |
| 1016 status = SSLHandshake(ssl_context_); | 1213 status = SSLHandshake(ssl_context_); |
| 1017 } | 1214 } |
| 1018 | 1215 |
| 1019 if (status == errSSLWouldBlock) { | 1216 if (status == errSSLWouldBlock) { |
| 1020 in_handshake_ = true; | 1217 in_handshake_ = true; |
| 1021 return noErr; | 1218 return noErr; |
| 1022 } | 1219 } |
| 1023 | 1220 |
| 1024 // Handshake succeeded. | 1221 // Handshake succeeded. |
| 1025 if ((in_handshake_) && (status == noErr)) { | 1222 if ((in_handshake_) && (status == noErr)) { |
| 1026 if (SSL_LOG_STATUS) { | 1223 if (SSL_LOG_STATUS) { |
| 1027 Log::Print("Finished with the Handshake\n"); | 1224 Log::PrintErr("Finished with the Handshake\n"); |
| 1028 } | 1225 } |
| 1029 connected_ = true; | 1226 connected_ = true; |
| 1030 } | 1227 } |
| 1031 return status; | 1228 return status; |
| 1032 } | 1229 } |
| 1033 | 1230 |
| 1034 | 1231 |
| 1035 // Returns false if Handshake should fail, and true if Handshake should | 1232 // Returns false if Handshake should fail, and true if Handshake should |
| 1036 // proceed. | 1233 // proceed. |
| 1037 Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) { | 1234 Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1051 "BadCertificateCallback returned a value that was not a boolean", | 1248 "BadCertificateCallback returned a value that was not a boolean", |
| 1052 Dart_Null())); | 1249 Dart_Null())); |
| 1053 } | 1250 } |
| 1054 return result; | 1251 return result; |
| 1055 } | 1252 } |
| 1056 | 1253 |
| 1057 | 1254 |
| 1058 OSStatus SSLFilter::CheckHandshake() { | 1255 OSStatus SSLFilter::CheckHandshake() { |
| 1059 if (bad_cert_ && in_handshake_) { | 1256 if (bad_cert_ && in_handshake_) { |
| 1060 if (SSL_LOG_STATUS) { | 1257 if (SSL_LOG_STATUS) { |
| 1061 Log::Print("Invoking bad certificate callback\n"); | 1258 Log::PrintErr("Invoking bad certificate callback\n"); |
| 1062 } | 1259 } |
| 1063 ASSERT(peer_certs_ != NULL); | 1260 ASSERT(peer_certs_ != NULL); |
| 1064 CFIndex peer_certs_len = CFArrayGetCount(peer_certs_); | 1261 CFIndex peer_certs_len = CFArrayGetCount(peer_certs_); |
| 1065 ASSERT(peer_certs_len > 0); | 1262 ASSERT(peer_certs_len > 0); |
| 1066 CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1); | 1263 CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1); |
| 1067 ASSERT(item != NULL); | 1264 ASSERT(item != NULL); |
| 1068 ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID()); | 1265 ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID()); |
| 1069 SecCertificateRef peer_cert = | 1266 SecCertificateRef peer_cert = |
| 1070 reinterpret_cast<SecCertificateRef>(const_cast<void*>(item)); | 1267 reinterpret_cast<SecCertificateRef>(const_cast<void*>(item)); |
| 1071 Dart_Handle result = InvokeBadCertCallback(peer_cert); | 1268 Dart_Handle result = InvokeBadCertCallback(peer_cert); |
| 1072 ThrowIfError(result); | 1269 ThrowIfError(result); |
| 1073 if (Dart_IsNull(result)) { | 1270 if (Dart_IsNull(result)) { |
| 1074 return errSSLBadCert; | 1271 return errSSLBadCert; |
| 1075 } else { | 1272 } else { |
| 1076 bool good_cert = DartUtils::GetBooleanValue(result); | 1273 bool good_cert = DartUtils::GetBooleanValue(result); |
| 1077 bad_cert_ = !good_cert; | 1274 bad_cert_ = !good_cert; |
| 1078 return good_cert ? noErr : errSSLBadCert; | 1275 return good_cert ? noErr : errSSLBadCert; |
| 1079 } | 1276 } |
| 1080 } | 1277 } |
| 1081 | 1278 |
| 1082 if (connected_ && in_handshake_) { | 1279 if (connected_ && in_handshake_) { |
| 1083 if (SSL_LOG_STATUS) { | 1280 if (SSL_LOG_STATUS) { |
| 1084 Log::Print("Invoking handshake complete callback\n"); | 1281 Log::PrintErr("Invoking handshake complete callback\n"); |
| 1085 } | 1282 } |
| 1086 ThrowIfError(Dart_InvokeClosure( | 1283 ThrowIfError(Dart_InvokeClosure( |
| 1087 Dart_HandleFromPersistent(handshake_complete_), 0, NULL)); | 1284 Dart_HandleFromPersistent(handshake_complete_), 0, NULL)); |
| 1088 in_handshake_ = false; | 1285 in_handshake_ = false; |
| 1089 } | 1286 } |
| 1090 return noErr; | 1287 return noErr; |
| 1091 } | 1288 } |
| 1092 | 1289 |
| 1093 | 1290 |
| 1094 void SSLFilter::Renegotiate(bool use_session_cache, | 1291 void SSLFilter::Renegotiate(bool use_session_cache, |
| 1095 bool request_client_certificate, | 1292 bool request_client_certificate, |
| 1096 bool require_client_certificate) { | 1293 bool require_client_certificate) { |
| 1097 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the | 1294 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the |
| 1098 // SSL_REQUEST_CERTIFICATE option is also set, so set it. | 1295 // SSL_REQUEST_CERTIFICATE option is also set, so set it. |
| 1099 request_client_certificate = | 1296 request_client_certificate = |
| 1100 request_client_certificate || require_client_certificate; | 1297 request_client_certificate || require_client_certificate; |
| 1101 // TODO(24070, 24069): Implement setting the client certificate parameters, | 1298 // TODO(24070, 24069): Implement setting the client certificate parameters, |
| 1102 // and triggering rehandshake. | 1299 // and triggering rehandshake. |
| 1103 } | 1300 } |
| 1104 | 1301 |
| 1105 | 1302 |
| 1106 SSLFilter::~SSLFilter() { | 1303 SSLFilter::~SSLFilter() { |
| 1107 // cert_context_ deleted by finalizer. Don't delete here. | |
| 1108 cert_context_ = NULL; | |
| 1109 if (ssl_context_ != NULL) { | 1304 if (ssl_context_ != NULL) { |
| 1110 CFRelease(ssl_context_); | 1305 CFRelease(ssl_context_); |
| 1111 ssl_context_ = NULL; | 1306 ssl_context_ = NULL; |
| 1112 } | 1307 } |
| 1113 if (peer_certs_ != NULL) { | 1308 if (peer_certs_ != NULL) { |
| 1114 CFRelease(peer_certs_); | 1309 CFRelease(peer_certs_); |
| 1115 peer_certs_ = NULL; | 1310 peer_certs_ = NULL; |
| 1116 } | 1311 } |
| 1117 if (hostname_ != NULL) { | 1312 if (hostname_ != NULL) { |
| 1118 free(hostname_); | 1313 free(hostname_); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 intptr_t bytes = requested < available ? requested : available; | 1390 intptr_t bytes = requested < available ? requested : available; |
| 1196 memmove(datap, &buffer[start], bytes); | 1391 memmove(datap, &buffer[start], bytes); |
| 1197 start += bytes; | 1392 start += bytes; |
| 1198 datap += bytes; | 1393 datap += bytes; |
| 1199 data_read += bytes; | 1394 data_read += bytes; |
| 1200 requested -= bytes; | 1395 requested -= bytes; |
| 1201 ASSERT(start <= end); | 1396 ASSERT(start <= end); |
| 1202 } | 1397 } |
| 1203 | 1398 |
| 1204 if (SSL_LOG_DATA) { | 1399 if (SSL_LOG_DATA) { |
| 1205 Log::Print("SSLReadCallback: requested: %ld, read %ld bytes\n", | 1400 Log::PrintErr("SSLReadCallback: requested: %ld, read %ld bytes\n", |
| 1206 *data_requested, data_read); | 1401 *data_requested, data_read); |
| 1207 } | 1402 } |
| 1208 | 1403 |
| 1209 filter->SetBufferStart(kReadEncrypted, start); | 1404 filter->SetBufferStart(kReadEncrypted, start); |
| 1210 bool short_read = data_read < static_cast<intptr_t>(*data_requested); | 1405 bool short_read = data_read < static_cast<intptr_t>(*data_requested); |
| 1211 *data_requested = data_read; | 1406 *data_requested = data_read; |
| 1212 return short_read ? errSSLWouldBlock : noErr; | 1407 return short_read ? errSSLWouldBlock : noErr; |
| 1213 } | 1408 } |
| 1214 | 1409 |
| 1215 | 1410 |
| 1216 // Read decrypted data from the filter to the circular buffer. | 1411 // Read decrypted data from the filter to the circular buffer. |
| 1217 OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start, | 1412 OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start, |
| 1218 intptr_t end, | 1413 intptr_t end, |
| 1219 intptr_t* bytes_processed) { | 1414 intptr_t* bytes_processed) { |
| 1220 ASSERT(bytes_processed != NULL); | 1415 ASSERT(bytes_processed != NULL); |
| 1221 intptr_t length = end - start; | 1416 intptr_t length = end - start; |
| 1222 OSStatus status = noErr; | 1417 OSStatus status = noErr; |
| 1223 size_t bytes = 0; | 1418 size_t bytes = 0; |
| 1224 if (length > 0) { | 1419 if (length > 0) { |
| 1225 status = SSLRead( | 1420 status = SSLRead( |
| 1226 ssl_context_, | 1421 ssl_context_, |
| 1227 reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)), | 1422 reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)), |
| 1228 length, | 1423 length, |
| 1229 &bytes); | 1424 &bytes); |
| 1230 if (SSL_LOG_STATUS) { | 1425 if (SSL_LOG_STATUS) { |
| 1231 Log::Print("SSLRead: status = %ld\n", static_cast<intptr_t>(status)); | 1426 Log::PrintErr("SSLRead: status = %ld\n", static_cast<intptr_t>(status)); |
| 1232 } | 1427 } |
| 1233 if ((status != noErr) && (status != errSSLWouldBlock)) { | 1428 if ((status != noErr) && (status != errSSLWouldBlock)) { |
| 1234 *bytes_processed = 0; | 1429 *bytes_processed = 0; |
| 1235 return status; | 1430 return status; |
| 1236 } | 1431 } |
| 1237 } | 1432 } |
| 1238 if (SSL_LOG_DATA) { | 1433 if (SSL_LOG_DATA) { |
| 1239 Log::Print("ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n", | 1434 Log::PrintErr( |
| 1435 "ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n", |
| 1240 length, bytes); | 1436 length, bytes); |
| 1241 } | 1437 } |
| 1242 *bytes_processed = static_cast<intptr_t>(bytes); | 1438 *bytes_processed = static_cast<intptr_t>(bytes); |
| 1243 return status; | 1439 return status; |
| 1244 } | 1440 } |
| 1245 | 1441 |
| 1246 | 1442 |
| 1247 OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection, | 1443 OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection, |
| 1248 const void* data, size_t* data_provided) { | 1444 const void* data, size_t* data_provided) { |
| 1249 // Copy at most `data_provided` bytes from data into | 1445 // Copy at most `data_provided` bytes from data into |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1286 intptr_t bytes = provided < available ? provided : available; | 1482 intptr_t bytes = provided < available ? provided : available; |
| 1287 memmove(&buffer[end], datap, bytes); | 1483 memmove(&buffer[end], datap, bytes); |
| 1288 end += bytes; | 1484 end += bytes; |
| 1289 datap += bytes; | 1485 datap += bytes; |
| 1290 data_written += bytes; | 1486 data_written += bytes; |
| 1291 provided -= bytes; | 1487 provided -= bytes; |
| 1292 ASSERT(end < start); | 1488 ASSERT(end < start); |
| 1293 } | 1489 } |
| 1294 | 1490 |
| 1295 if (SSL_LOG_DATA) { | 1491 if (SSL_LOG_DATA) { |
| 1296 Log::Print("SSLWriteCallback: provided: %ld, written %ld bytes\n", | 1492 Log::PrintErr("SSLWriteCallback: provided: %ld, written %ld bytes\n", |
| 1297 *data_provided, data_written); | 1493 *data_provided, data_written); |
| 1298 } | 1494 } |
| 1299 | 1495 |
| 1300 filter->SetBufferEnd(kWriteEncrypted, end); | 1496 filter->SetBufferEnd(kWriteEncrypted, end); |
| 1301 *data_provided = data_written; | 1497 *data_provided = data_written; |
| 1302 return (data_written == 0) ? errSSLWouldBlock : noErr; | 1498 return (data_written == 0) ? errSSLWouldBlock : noErr; |
| 1303 } | 1499 } |
| 1304 | 1500 |
| 1305 | 1501 |
| 1306 OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start, | 1502 OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start, |
| 1307 intptr_t end, | 1503 intptr_t end, |
| 1308 intptr_t* bytes_processed) { | 1504 intptr_t* bytes_processed) { |
| 1309 ASSERT(bytes_processed != NULL); | 1505 ASSERT(bytes_processed != NULL); |
| 1310 intptr_t length = end - start; | 1506 intptr_t length = end - start; |
| 1311 OSStatus status = noErr; | 1507 OSStatus status = noErr; |
| 1312 size_t bytes = 0; | 1508 size_t bytes = 0; |
| 1313 if (length > 0) { | 1509 if (length > 0) { |
| 1314 status = SSLWrite( | 1510 status = SSLWrite( |
| 1315 ssl_context_, | 1511 ssl_context_, |
| 1316 reinterpret_cast<void*>(buffers_[kWritePlaintext] + start), | 1512 reinterpret_cast<void*>(buffers_[kWritePlaintext] + start), |
| 1317 length, | 1513 length, |
| 1318 &bytes); | 1514 &bytes); |
| 1319 if (SSL_LOG_STATUS) { | 1515 if (SSL_LOG_STATUS) { |
| 1320 Log::Print("SSLWrite: status = %ld\n", static_cast<intptr_t>(status)); | 1516 Log::PrintErr("SSLWrite: status = %ld\n", static_cast<intptr_t>(status)); |
| 1321 } | 1517 } |
| 1322 if ((status != noErr) && (status != errSSLWouldBlock)) { | 1518 if ((status != noErr) && (status != errSSLWouldBlock)) { |
| 1323 *bytes_processed = 0; | 1519 *bytes_processed = 0; |
| 1324 return status; | 1520 return status; |
| 1325 } | 1521 } |
| 1326 } | 1522 } |
| 1327 if (SSL_LOG_DATA) { | 1523 if (SSL_LOG_DATA) { |
| 1328 Log::Print("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n", | 1524 Log::PrintErr("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n", |
| 1329 length, bytes); | 1525 length, bytes); |
| 1330 } | 1526 } |
| 1331 *bytes_processed = static_cast<intptr_t>(bytes); | 1527 *bytes_processed = static_cast<intptr_t>(bytes); |
| 1332 return status; | 1528 return status; |
| 1333 } | 1529 } |
| 1334 | 1530 |
| 1335 } // namespace bin | 1531 } // namespace bin |
| 1336 } // namespace dart | 1532 } // namespace dart |
| 1337 | 1533 |
| 1338 #endif // TARGET_OS_IOS | 1534 #endif // TARGET_OS_IOS |
| 1339 | 1535 |
| 1340 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1536 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| OLD | NEW |