| 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. |
| 262 Dart_Handle err = SetFilter(args, filter); | 386 Dart_Handle err = SetFilter(args, filter); |
| 263 if (Dart_IsError(err)) { | 387 if (Dart_IsError(err)) { |
| 264 delete filter; | 388 filter->Release(); |
| 265 Dart_PropagateError(err); | 389 Dart_PropagateError(err); |
| 266 } | 390 } |
| 267 err = filter->Init(dart_this); | 391 err = filter->Init(dart_this); |
| 268 if (Dart_IsError(err)) { | 392 if (Dart_IsError(err)) { |
| 269 // The finalizer was set up by SetFilter. It will delete `filter` if there | 393 // The finalizer was set up by SetFilter. It will delete `filter` if there |
| 270 // is an error. | 394 // is an error. |
| 271 filter->Destroy(); | 395 filter->Destroy(); |
| 272 Dart_PropagateError(err); | 396 Dart_PropagateError(err); |
| 273 } | 397 } |
| 274 } | 398 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 GetFilter(args)->RegisterBadCertificateCallback(callback); | 489 GetFilter(args)->RegisterBadCertificateCallback(callback); |
| 366 } | 490 } |
| 367 | 491 |
| 368 | 492 |
| 369 void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) { | 493 void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) { |
| 370 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); | 494 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); |
| 371 } | 495 } |
| 372 | 496 |
| 373 | 497 |
| 374 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { | 498 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { |
| 375 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); | 499 SSLFilter* filter = GetFilter(args); |
| 500 // This filter pointer is passed to the IO Service thread. The IO Service |
| 501 // thread must Release() the pointer when it is done with it. |
| 502 filter->Retain(); |
| 503 intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter); |
| 376 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); | 504 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); |
| 377 } | 505 } |
| 378 | 506 |
| 379 | 507 |
| 380 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { | 508 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { |
| 381 SSLCertContext* cert_context = new SSLCertContext(); | 509 SSLCertContext* cert_context = new SSLCertContext(); |
| 382 // cert_context deleted in DeleteCertContext finalizer. | 510 // cert_context deleted in DeleteCertContext finalizer. |
| 383 Dart_Handle err = SetSecurityContext(args, cert_context); | 511 Dart_Handle err = SetSecurityContext(args, cert_context); |
| 384 if (Dart_IsError(err)) { | 512 if (Dart_IsError(err)) { |
| 385 delete cert_context; | 513 cert_context->Release(); |
| 386 Dart_PropagateError(err); | 514 Dart_PropagateError(err); |
| 387 } | 515 } |
| 388 } | 516 } |
| 389 | 517 |
| 390 | 518 |
| 391 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 519 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
| 392 Dart_NativeArguments args) { | 520 Dart_NativeArguments args) { |
| 393 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 521 SSLCertContext* context = GetSecurityContext(args); |
| 394 "SecurityContext.usePrivateKeyBytes is not yet implemented.")); | 522 const char* password = GetPasswordArgument(args, 2); |
| 523 |
| 524 OSStatus status; |
| 525 CFArrayRef cert_chain = NULL; |
| 526 SecIdentityRef identity = NULL; |
| 527 { |
| 528 ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 529 status = ExtractSecItems( |
| 530 buffer.get(), buffer.length(), password, &cert_chain, &identity); |
| 531 } |
| 532 |
| 533 // Set the context fields. Repeated calls to usePrivateKeyBytes are an error. |
| 534 bool set_failure = false; |
| 535 if ((identity != NULL) && !context->set_identity(identity)) { |
| 536 CFRelease(identity); |
| 537 if (cert_chain != NULL) { |
| 538 CFRelease(cert_chain); |
| 539 } |
| 540 set_failure = true; |
| 541 } |
| 542 |
| 543 // We can't have set a cert_chain without also having set an identity. |
| 544 // That is, if context->set_identity() succeeds, then it is impossible for |
| 545 // context->set_cert_chain() to fail. This is because SecPKCS12Import never |
| 546 // returns a cert chain without also returning a private key. |
| 547 ASSERT(set_failure || (context->cert_chain() == NULL)); |
| 548 if (!set_failure && (cert_chain != NULL)) { |
| 549 context->set_cert_chain(cert_chain); |
| 550 } |
| 551 |
| 552 if (set_failure) { |
| 553 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 554 "usePrivateKeyBytes has already been called on the given context.")); |
| 555 } |
| 556 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); |
| 395 } | 557 } |
| 396 | 558 |
| 397 | 559 |
| 398 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 560 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
| 399 Dart_NativeArguments args) { | 561 Dart_NativeArguments args) { |
| 400 SSLCertContext* context = GetSecurityContext(args); | 562 SSLCertContext* context = GetSecurityContext(args); |
| 401 | 563 |
| 402 OSStatus status = noErr; | 564 OSStatus status = noErr; |
| 403 SecCertificateRef cert = NULL; | 565 SecCertificateRef cert = NULL; |
| 404 { | 566 { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 426 | 588 |
| 427 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 589 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
| 428 Dart_NativeArguments args) { | 590 Dart_NativeArguments args) { |
| 429 SSLCertContext* context = GetSecurityContext(args); | 591 SSLCertContext* context = GetSecurityContext(args); |
| 430 context->set_trust_builtin(true); | 592 context->set_trust_builtin(true); |
| 431 } | 593 } |
| 432 | 594 |
| 433 | 595 |
| 434 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 596 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
| 435 Dart_NativeArguments args) { | 597 Dart_NativeArguments args) { |
| 436 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 598 // This is a no-op on iOS. We get the cert chain along with the private key |
| 437 "SecurityContext.useCertificateChainBytes is not yet implemented.")); | 599 // in UsePrivateyKeyBytes(). |
| 438 } | 600 } |
| 439 | 601 |
| 440 | 602 |
| 441 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 603 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
| 442 Dart_NativeArguments args) { | 604 Dart_NativeArguments args) { |
| 443 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 605 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
| 444 "SecurityContext.setClientAuthoritiesBytes is not yet implemented.")); | 606 "SecurityContext.setClientAuthoritiesBytes is not supported on this " |
| 607 "platform.")); |
| 445 } | 608 } |
| 446 | 609 |
| 447 | 610 |
| 448 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( | 611 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( |
| 449 Dart_NativeArguments args) { | 612 Dart_NativeArguments args) { |
| 450 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 613 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
| 451 "ALPN is not supported on this platform")); | 614 "ALPN is not supported on this platform")); |
| 452 } | 615 } |
| 453 | 616 |
| 454 | 617 |
| 455 void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) { | 618 void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) { |
| 456 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 619 SecCertificateRef certificate = GetX509Certificate(args); |
| 457 "X509Certificate.subject is not yet implemented.")); | 620 CFStringRef cfsubject = SecCertificateCopySubjectSummary(certificate); |
| 621 if (cfsubject != NULL) { |
| 622 char* csubject = CFStringRefToCString(cfsubject); |
| 623 CFRelease(cfsubject); |
| 624 Dart_SetReturnValue(args, Dart_NewStringFromCString(csubject)); |
| 625 } else { |
| 626 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 627 "X509.subject failed to find subject's common name.")); |
| 628 } |
| 458 } | 629 } |
| 459 | 630 |
| 460 | 631 |
| 461 void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) { | 632 void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) { |
| 462 Dart_ThrowException(DartUtils::NewDartUnsupportedError( | 633 Dart_ThrowException(DartUtils::NewDartUnsupportedError( |
| 463 "X509Certificate.issuer is not supported on this platform.")); | 634 "X509Certificate.issuer is not supported on this platform.")); |
| 464 } | 635 } |
| 465 | 636 |
| 466 | 637 |
| 467 void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) { | 638 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 | 662 // 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 | 663 // 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. | 664 // the data space of output buffers, and modify the start pointer. |
| 494 // | 665 // |
| 495 // When ProcessFilter returns, the Dart thread is responsible for combining | 666 // 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 | 667 // the updated pointers from Dart and C++, to make the new valid state of |
| 497 // the circular buffer. | 668 // the circular buffer. |
| 498 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) { | 669 CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) { |
| 499 CObjectIntptr filter_object(request[0]); | 670 CObjectIntptr filter_object(request[0]); |
| 500 SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value()); | 671 SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value()); |
| 672 RefCntReleaseScope<SSLFilter> rs(filter); |
| 673 |
| 501 bool in_handshake = CObjectBool(request[1]).Value(); | 674 bool in_handshake = CObjectBool(request[1]).Value(); |
| 502 intptr_t starts[SSLFilter::kNumBuffers]; | 675 intptr_t starts[SSLFilter::kNumBuffers]; |
| 503 intptr_t ends[SSLFilter::kNumBuffers]; | 676 intptr_t ends[SSLFilter::kNumBuffers]; |
| 504 for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) { | 677 for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) { |
| 505 starts[i] = CObjectInt32(request[2 * i + 2]).Value(); | 678 starts[i] = CObjectInt32(request[2 * i + 2]).Value(); |
| 506 ends[i] = CObjectInt32(request[2 * i + 3]).Value(); | 679 ends[i] = CObjectInt32(request[2 * i + 3]).Value(); |
| 507 } | 680 } |
| 508 | 681 |
| 509 OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake); | 682 OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake); |
| 510 if (status == noErr) { | 683 if (status == noErr) { |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 ssl_context, kSSLSessionOptionBreakOnServerAuth, true); | 1030 ssl_context, kSSLSessionOptionBreakOnServerAuth, true); |
| 858 CheckStatus(status, | 1031 CheckStatus(status, |
| 859 "TlsException", | 1032 "TlsException", |
| 860 "Failed to set BreakOnServerAuth option"); | 1033 "Failed to set BreakOnServerAuth option"); |
| 861 | 1034 |
| 862 status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1); | 1035 status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1); |
| 863 CheckStatus(status, | 1036 CheckStatus(status, |
| 864 "TlsException", | 1037 "TlsException", |
| 865 "Failed to set minimum protocol version to kTLSProtocol1"); | 1038 "Failed to set minimum protocol version to kTLSProtocol1"); |
| 866 | 1039 |
| 1040 // If the context has an identity pass it to SSLSetCertificate(). |
| 1041 if (context->identity() != NULL) { |
| 1042 CFMutableArrayRef chain = |
| 1043 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
| 1044 CFArrayAppendValue(chain, context->identity()); |
| 1045 |
| 1046 // Append the certificate chain if there is one. |
| 1047 if (context->cert_chain() != NULL) { |
| 1048 // Skip the first one, it's already included in the identity. |
| 1049 CFIndex chain_length = CFArrayGetCount(context->cert_chain()); |
| 1050 if (chain_length > 1) { |
| 1051 CFArrayAppendArray( |
| 1052 chain, context->cert_chain(), CFRangeMake(1, chain_length)); |
| 1053 } |
| 1054 } |
| 1055 |
| 1056 status = SSLSetCertificate(ssl_context, chain); |
| 1057 CFRelease(chain); |
| 1058 CheckStatus(status, "TlsException", "SSLSetCertificate failed"); |
| 1059 } |
| 1060 |
| 867 if (is_server) { | 1061 if (is_server) { |
| 868 SSLAuthenticate auth = | 1062 SSLAuthenticate auth = |
| 869 require_client_certificate | 1063 require_client_certificate |
| 870 ? kAlwaysAuthenticate | 1064 ? kAlwaysAuthenticate |
| 871 : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate); | 1065 : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate); |
| 872 status = SSLSetClientSideAuthenticate(ssl_context, auth); | 1066 status = SSLSetClientSideAuthenticate(ssl_context, auth); |
| 873 CheckStatus(status, | 1067 CheckStatus(status, |
| 874 "TlsException", | 1068 "TlsException", |
| 875 "Failed to set client authentication mode"); | 1069 "Failed to set client authentication mode"); |
| 876 | 1070 |
| 877 // If we're at least trying client authentication, then break handshake | 1071 // If we're at least trying client authentication, then break handshake |
| 878 // for client authentication. | 1072 // for client authentication. |
| 879 if (auth != kNeverAuthenticate) { | 1073 if (auth != kNeverAuthenticate) { |
| 880 status = SSLSetSessionOption( | 1074 status = SSLSetSessionOption( |
| 881 ssl_context, kSSLSessionOptionBreakOnClientAuth, true); | 1075 ssl_context, kSSLSessionOptionBreakOnClientAuth, true); |
| 882 CheckStatus(status, | 1076 CheckStatus(status, |
| 883 "TlsException", | 1077 "TlsException", |
| 884 "Failed to set client authentication mode"); | 1078 "Failed to set client authentication mode"); |
| 885 } | 1079 } |
| 886 } | 1080 } |
| 887 | 1081 |
| 888 // Add the contexts to our wrapper. | 1082 // Add the contexts to our wrapper. |
| 889 cert_context_ = context; | 1083 cert_context_.set(context); |
| 890 ssl_context_ = ssl_context; | 1084 ssl_context_ = ssl_context; |
| 891 is_server_ = is_server; | 1085 is_server_ = is_server; |
| 892 | 1086 |
| 893 // Kick-off the handshake. Expect the handshake to need more data. | 1087 // Kick-off the handshake. Expect the handshake to need more data. |
| 894 // SSLHandshake calls our SSLReadCallback and SSLWriteCallback. | 1088 // SSLHandshake calls our SSLReadCallback and SSLWriteCallback. |
| 895 status = SSLHandshake(ssl_context); | 1089 status = SSLHandshake(ssl_context); |
| 896 ASSERT(status != noErr); | 1090 ASSERT(status != noErr); |
| 897 if (status == errSSLWouldBlock) { | 1091 if (status == errSSLWouldBlock) { |
| 898 status = noErr; | 1092 status = noErr; |
| 899 in_handshake_ = true; | 1093 in_handshake_ = true; |
| 900 } | 1094 } |
| 901 CheckStatus(status, | 1095 CheckStatus(status, |
| 902 "HandshakeException", | 1096 "HandshakeException", |
| 903 is_server_ ? "Handshake error in server" : "Handshake error in client"); | 1097 is_server_ ? "Handshake error in server" : "Handshake error in client"); |
| 904 } | 1098 } |
| 905 | 1099 |
| 906 | 1100 |
| 907 OSStatus SSLFilter::EvaluatePeerTrust() { | 1101 OSStatus SSLFilter::EvaluatePeerTrust() { |
| 908 OSStatus status = noErr; | 1102 OSStatus status = noErr; |
| 909 | 1103 |
| 910 if (SSL_LOG_STATUS) { | 1104 if (SSL_LOG_STATUS) { |
| 911 Log::Print("Handshake evaluating trust.\n"); | 1105 Log::PrintErr("Handshake evaluating trust.\n"); |
| 912 } | 1106 } |
| 913 SecTrustRef peer_trust = NULL; | 1107 SecTrustRef peer_trust = NULL; |
| 914 status = SSLCopyPeerTrust(ssl_context_, &peer_trust); | 1108 status = SSLCopyPeerTrust(ssl_context_, &peer_trust); |
| 915 if (status != noErr) { | 1109 if (status != noErr) { |
| 916 if (is_server_ && (status == errSSLBadCert)) { | 1110 if (is_server_ && (status == errSSLBadCert)) { |
| 917 // A client certificate was requested, but not required, and wasn't sent. | 1111 // A client certificate was requested, but not required, and wasn't sent. |
| 918 return noErr; | 1112 return noErr; |
| 919 } | 1113 } |
| 920 if (SSL_LOG_STATUS) { | 1114 if (SSL_LOG_STATUS) { |
| 921 Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n", | 1115 Log::PrintErr("Handshake error from SSLCopyPeerTrust(): %ld.\n", |
| 922 static_cast<intptr_t>(status)); | 1116 static_cast<intptr_t>(status)); |
| 923 } | 1117 } |
| 924 return status; | 1118 return status; |
| 925 } | 1119 } |
| 926 | 1120 |
| 927 CFArrayRef trusted_certs = NULL; | 1121 CFArrayRef trusted_certs = NULL; |
| 928 if (cert_context_->trusted_certs() != NULL) { | 1122 if (cert_context_.get()->trusted_certs() != NULL) { |
| 929 trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs()); | 1123 trusted_certs = |
| 1124 CFArrayCreateCopy(NULL, cert_context_.get()->trusted_certs()); |
| 930 } else { | 1125 } else { |
| 931 trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); | 1126 trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); |
| 932 } | 1127 } |
| 933 | 1128 |
| 934 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); | 1129 status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs); |
| 935 if (status != noErr) { | 1130 if (status != noErr) { |
| 936 if (SSL_LOG_STATUS) { | 1131 if (SSL_LOG_STATUS) { |
| 937 Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n", | 1132 Log::PrintErr("Handshake error from SecTrustSetAnchorCertificates: %ld\n", |
| 938 static_cast<intptr_t>(status)); | 1133 static_cast<intptr_t>(status)); |
| 939 } | 1134 } |
| 940 CFRelease(trusted_certs); | 1135 CFRelease(trusted_certs); |
| 941 CFRelease(peer_trust); | 1136 CFRelease(peer_trust); |
| 942 return status; | 1137 return status; |
| 943 } | 1138 } |
| 944 | 1139 |
| 945 if (SSL_LOG_STATUS) { | 1140 if (SSL_LOG_STATUS) { |
| 946 Log::Print("Handshake %s built in root certs\n", | 1141 Log::PrintErr("Handshake %s built in root certs\n", |
| 947 cert_context_->trust_builtin() ? "trusting" : "not trusting"); | 1142 cert_context_.get()->trust_builtin() ? "trusting" : "not trusting"); |
| 948 } | 1143 } |
| 949 | 1144 |
| 950 status = SecTrustSetAnchorCertificatesOnly( | 1145 status = SecTrustSetAnchorCertificatesOnly( |
| 951 peer_trust, !cert_context_->trust_builtin()); | 1146 peer_trust, !cert_context_.get()->trust_builtin()); |
| 952 if (status != noErr) { | 1147 if (status != noErr) { |
| 953 CFRelease(trusted_certs); | 1148 CFRelease(trusted_certs); |
| 954 CFRelease(peer_trust); | 1149 CFRelease(peer_trust); |
| 955 return status; | 1150 return status; |
| 956 } | 1151 } |
| 957 | 1152 |
| 958 SecTrustResultType trust_result; | 1153 SecTrustResultType trust_result; |
| 959 status = SecTrustEvaluate(peer_trust, &trust_result); | 1154 status = SecTrustEvaluate(peer_trust, &trust_result); |
| 960 if (status != noErr) { | 1155 if (status != noErr) { |
| 961 CFRelease(trusted_certs); | 1156 CFRelease(trusted_certs); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 975 | 1170 |
| 976 CFRelease(trusted_certs); | 1171 CFRelease(trusted_certs); |
| 977 CFRelease(peer_trust); | 1172 CFRelease(peer_trust); |
| 978 | 1173 |
| 979 if ((trust_result == kSecTrustResultProceed) || | 1174 if ((trust_result == kSecTrustResultProceed) || |
| 980 (trust_result == kSecTrustResultUnspecified)) { | 1175 (trust_result == kSecTrustResultUnspecified)) { |
| 981 // Trusted. | 1176 // Trusted. |
| 982 return noErr; | 1177 return noErr; |
| 983 } else { | 1178 } else { |
| 984 if (SSL_LOG_STATUS) { | 1179 if (SSL_LOG_STATUS) { |
| 985 Log::Print("Trust eval failed: trust_restul = %d\n", trust_result); | 1180 Log::PrintErr("Trust eval failed: trust_result = %d\n", trust_result); |
| 986 } | 1181 } |
| 987 bad_cert_ = true; | 1182 bad_cert_ = true; |
| 988 return errSSLBadCert; | 1183 return errSSLBadCert; |
| 989 } | 1184 } |
| 990 } | 1185 } |
| 991 | 1186 |
| 992 | 1187 |
| 993 OSStatus SSLFilter::Handshake() { | 1188 OSStatus SSLFilter::Handshake() { |
| 994 ASSERT(cert_context_ != NULL); | 1189 ASSERT(cert_context_.get() != NULL); |
| 995 ASSERT(ssl_context_ != NULL); | 1190 ASSERT(ssl_context_ != NULL); |
| 996 // Try and push handshake along. | 1191 // Try and push handshake along. |
| 997 if (SSL_LOG_STATUS) { | 1192 if (SSL_LOG_STATUS) { |
| 998 Log::Print("Doing SSLHandshake\n"); | 1193 Log::PrintErr("Doing SSLHandshake\n"); |
| 999 } | 1194 } |
| 1000 OSStatus status = SSLHandshake(ssl_context_); | 1195 OSStatus status = SSLHandshake(ssl_context_); |
| 1001 if (SSL_LOG_STATUS) { | 1196 if (SSL_LOG_STATUS) { |
| 1002 Log::Print("SSLHandshake returned %ld\n", static_cast<intptr_t>(status)); | 1197 Log::PrintErr("SSLHandshake returned %ld\n", static_cast<intptr_t>(status)); |
| 1003 } | 1198 } |
| 1004 | 1199 |
| 1005 if ((status == errSSLServerAuthCompleted) || | 1200 if ((status == errSSLServerAuthCompleted) || |
| 1006 (status == errSSLClientAuthCompleted)) { | 1201 (status == errSSLClientAuthCompleted)) { |
| 1007 status = EvaluatePeerTrust(); | 1202 status = EvaluatePeerTrust(); |
| 1008 if (status == errSSLBadCert) { | 1203 if (status == errSSLBadCert) { |
| 1009 // Need to invoke the bad certificate callback. | 1204 // Need to invoke the bad certificate callback. |
| 1010 return noErr; | 1205 return noErr; |
| 1011 } else if (status != noErr) { | 1206 } else if (status != noErr) { |
| 1012 return status; | 1207 return status; |
| 1013 } | 1208 } |
| 1014 // When trust evaluation succeeds, we can call SSLHandshake again | 1209 // When trust evaluation succeeds, we can call SSLHandshake again |
| 1015 // immediately. | 1210 // immediately. |
| 1016 status = SSLHandshake(ssl_context_); | 1211 status = SSLHandshake(ssl_context_); |
| 1017 } | 1212 } |
| 1018 | 1213 |
| 1019 if (status == errSSLWouldBlock) { | 1214 if (status == errSSLWouldBlock) { |
| 1020 in_handshake_ = true; | 1215 in_handshake_ = true; |
| 1021 return noErr; | 1216 return noErr; |
| 1022 } | 1217 } |
| 1023 | 1218 |
| 1024 // Handshake succeeded. | 1219 // Handshake succeeded. |
| 1025 if ((in_handshake_) && (status == noErr)) { | 1220 if ((in_handshake_) && (status == noErr)) { |
| 1026 if (SSL_LOG_STATUS) { | 1221 if (SSL_LOG_STATUS) { |
| 1027 Log::Print("Finished with the Handshake\n"); | 1222 Log::PrintErr("Finished with the Handshake\n"); |
| 1028 } | 1223 } |
| 1029 connected_ = true; | 1224 connected_ = true; |
| 1030 } | 1225 } |
| 1031 return status; | 1226 return status; |
| 1032 } | 1227 } |
| 1033 | 1228 |
| 1034 | 1229 |
| 1035 // Returns false if Handshake should fail, and true if Handshake should | 1230 // Returns false if Handshake should fail, and true if Handshake should |
| 1036 // proceed. | 1231 // proceed. |
| 1037 Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) { | 1232 Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1051 "BadCertificateCallback returned a value that was not a boolean", | 1246 "BadCertificateCallback returned a value that was not a boolean", |
| 1052 Dart_Null())); | 1247 Dart_Null())); |
| 1053 } | 1248 } |
| 1054 return result; | 1249 return result; |
| 1055 } | 1250 } |
| 1056 | 1251 |
| 1057 | 1252 |
| 1058 OSStatus SSLFilter::CheckHandshake() { | 1253 OSStatus SSLFilter::CheckHandshake() { |
| 1059 if (bad_cert_ && in_handshake_) { | 1254 if (bad_cert_ && in_handshake_) { |
| 1060 if (SSL_LOG_STATUS) { | 1255 if (SSL_LOG_STATUS) { |
| 1061 Log::Print("Invoking bad certificate callback\n"); | 1256 Log::PrintErr("Invoking bad certificate callback\n"); |
| 1062 } | 1257 } |
| 1063 ASSERT(peer_certs_ != NULL); | 1258 ASSERT(peer_certs_ != NULL); |
| 1064 CFIndex peer_certs_len = CFArrayGetCount(peer_certs_); | 1259 CFIndex peer_certs_len = CFArrayGetCount(peer_certs_); |
| 1065 ASSERT(peer_certs_len > 0); | 1260 ASSERT(peer_certs_len > 0); |
| 1066 CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1); | 1261 CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1); |
| 1067 ASSERT(item != NULL); | 1262 ASSERT(item != NULL); |
| 1068 ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID()); | 1263 ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID()); |
| 1069 SecCertificateRef peer_cert = | 1264 SecCertificateRef peer_cert = |
| 1070 reinterpret_cast<SecCertificateRef>(const_cast<void*>(item)); | 1265 reinterpret_cast<SecCertificateRef>(const_cast<void*>(item)); |
| 1071 Dart_Handle result = InvokeBadCertCallback(peer_cert); | 1266 Dart_Handle result = InvokeBadCertCallback(peer_cert); |
| 1072 ThrowIfError(result); | 1267 ThrowIfError(result); |
| 1073 if (Dart_IsNull(result)) { | 1268 if (Dart_IsNull(result)) { |
| 1074 return errSSLBadCert; | 1269 return errSSLBadCert; |
| 1075 } else { | 1270 } else { |
| 1076 bool good_cert = DartUtils::GetBooleanValue(result); | 1271 bool good_cert = DartUtils::GetBooleanValue(result); |
| 1077 bad_cert_ = !good_cert; | 1272 bad_cert_ = !good_cert; |
| 1078 return good_cert ? noErr : errSSLBadCert; | 1273 return good_cert ? noErr : errSSLBadCert; |
| 1079 } | 1274 } |
| 1080 } | 1275 } |
| 1081 | 1276 |
| 1082 if (connected_ && in_handshake_) { | 1277 if (connected_ && in_handshake_) { |
| 1083 if (SSL_LOG_STATUS) { | 1278 if (SSL_LOG_STATUS) { |
| 1084 Log::Print("Invoking handshake complete callback\n"); | 1279 Log::PrintErr("Invoking handshake complete callback\n"); |
| 1085 } | 1280 } |
| 1086 ThrowIfError(Dart_InvokeClosure( | 1281 ThrowIfError(Dart_InvokeClosure( |
| 1087 Dart_HandleFromPersistent(handshake_complete_), 0, NULL)); | 1282 Dart_HandleFromPersistent(handshake_complete_), 0, NULL)); |
| 1088 in_handshake_ = false; | 1283 in_handshake_ = false; |
| 1089 } | 1284 } |
| 1090 return noErr; | 1285 return noErr; |
| 1091 } | 1286 } |
| 1092 | 1287 |
| 1093 | 1288 |
| 1094 void SSLFilter::Renegotiate(bool use_session_cache, | 1289 void SSLFilter::Renegotiate(bool use_session_cache, |
| 1095 bool request_client_certificate, | 1290 bool request_client_certificate, |
| 1096 bool require_client_certificate) { | 1291 bool require_client_certificate) { |
| 1097 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the | 1292 // The SSL_REQUIRE_CERTIFICATE option only takes effect if the |
| 1098 // SSL_REQUEST_CERTIFICATE option is also set, so set it. | 1293 // SSL_REQUEST_CERTIFICATE option is also set, so set it. |
| 1099 request_client_certificate = | 1294 request_client_certificate = |
| 1100 request_client_certificate || require_client_certificate; | 1295 request_client_certificate || require_client_certificate; |
| 1101 // TODO(24070, 24069): Implement setting the client certificate parameters, | 1296 // TODO(24070, 24069): Implement setting the client certificate parameters, |
| 1102 // and triggering rehandshake. | 1297 // and triggering rehandshake. |
| 1103 } | 1298 } |
| 1104 | 1299 |
| 1105 | 1300 |
| 1106 SSLFilter::~SSLFilter() { | 1301 SSLFilter::~SSLFilter() { |
| 1107 // cert_context_ deleted by finalizer. Don't delete here. | |
| 1108 cert_context_ = NULL; | |
| 1109 if (ssl_context_ != NULL) { | 1302 if (ssl_context_ != NULL) { |
| 1110 CFRelease(ssl_context_); | 1303 CFRelease(ssl_context_); |
| 1111 ssl_context_ = NULL; | 1304 ssl_context_ = NULL; |
| 1112 } | 1305 } |
| 1113 if (peer_certs_ != NULL) { | 1306 if (peer_certs_ != NULL) { |
| 1114 CFRelease(peer_certs_); | 1307 CFRelease(peer_certs_); |
| 1115 peer_certs_ = NULL; | 1308 peer_certs_ = NULL; |
| 1116 } | 1309 } |
| 1117 if (hostname_ != NULL) { | 1310 if (hostname_ != NULL) { |
| 1118 free(hostname_); | 1311 free(hostname_); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 intptr_t bytes = requested < available ? requested : available; | 1388 intptr_t bytes = requested < available ? requested : available; |
| 1196 memmove(datap, &buffer[start], bytes); | 1389 memmove(datap, &buffer[start], bytes); |
| 1197 start += bytes; | 1390 start += bytes; |
| 1198 datap += bytes; | 1391 datap += bytes; |
| 1199 data_read += bytes; | 1392 data_read += bytes; |
| 1200 requested -= bytes; | 1393 requested -= bytes; |
| 1201 ASSERT(start <= end); | 1394 ASSERT(start <= end); |
| 1202 } | 1395 } |
| 1203 | 1396 |
| 1204 if (SSL_LOG_DATA) { | 1397 if (SSL_LOG_DATA) { |
| 1205 Log::Print("SSLReadCallback: requested: %ld, read %ld bytes\n", | 1398 Log::PrintErr("SSLReadCallback: requested: %ld, read %ld bytes\n", |
| 1206 *data_requested, data_read); | 1399 *data_requested, data_read); |
| 1207 } | 1400 } |
| 1208 | 1401 |
| 1209 filter->SetBufferStart(kReadEncrypted, start); | 1402 filter->SetBufferStart(kReadEncrypted, start); |
| 1210 bool short_read = data_read < static_cast<intptr_t>(*data_requested); | 1403 bool short_read = data_read < static_cast<intptr_t>(*data_requested); |
| 1211 *data_requested = data_read; | 1404 *data_requested = data_read; |
| 1212 return short_read ? errSSLWouldBlock : noErr; | 1405 return short_read ? errSSLWouldBlock : noErr; |
| 1213 } | 1406 } |
| 1214 | 1407 |
| 1215 | 1408 |
| 1216 // Read decrypted data from the filter to the circular buffer. | 1409 // Read decrypted data from the filter to the circular buffer. |
| 1217 OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start, | 1410 OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start, |
| 1218 intptr_t end, | 1411 intptr_t end, |
| 1219 intptr_t* bytes_processed) { | 1412 intptr_t* bytes_processed) { |
| 1220 ASSERT(bytes_processed != NULL); | 1413 ASSERT(bytes_processed != NULL); |
| 1221 intptr_t length = end - start; | 1414 intptr_t length = end - start; |
| 1222 OSStatus status = noErr; | 1415 OSStatus status = noErr; |
| 1223 size_t bytes = 0; | 1416 size_t bytes = 0; |
| 1224 if (length > 0) { | 1417 if (length > 0) { |
| 1225 status = SSLRead( | 1418 status = SSLRead( |
| 1226 ssl_context_, | 1419 ssl_context_, |
| 1227 reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)), | 1420 reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)), |
| 1228 length, | 1421 length, |
| 1229 &bytes); | 1422 &bytes); |
| 1230 if (SSL_LOG_STATUS) { | 1423 if (SSL_LOG_STATUS) { |
| 1231 Log::Print("SSLRead: status = %ld\n", static_cast<intptr_t>(status)); | 1424 Log::PrintErr("SSLRead: status = %ld\n", static_cast<intptr_t>(status)); |
| 1232 } | 1425 } |
| 1233 if ((status != noErr) && (status != errSSLWouldBlock)) { | 1426 if ((status != noErr) && (status != errSSLWouldBlock)) { |
| 1234 *bytes_processed = 0; | 1427 *bytes_processed = 0; |
| 1235 return status; | 1428 return status; |
| 1236 } | 1429 } |
| 1237 } | 1430 } |
| 1238 if (SSL_LOG_DATA) { | 1431 if (SSL_LOG_DATA) { |
| 1239 Log::Print("ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n", | 1432 Log::PrintErr( |
| 1433 "ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n", |
| 1240 length, bytes); | 1434 length, bytes); |
| 1241 } | 1435 } |
| 1242 *bytes_processed = static_cast<intptr_t>(bytes); | 1436 *bytes_processed = static_cast<intptr_t>(bytes); |
| 1243 return status; | 1437 return status; |
| 1244 } | 1438 } |
| 1245 | 1439 |
| 1246 | 1440 |
| 1247 OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection, | 1441 OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection, |
| 1248 const void* data, size_t* data_provided) { | 1442 const void* data, size_t* data_provided) { |
| 1249 // Copy at most `data_provided` bytes from data into | 1443 // 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; | 1480 intptr_t bytes = provided < available ? provided : available; |
| 1287 memmove(&buffer[end], datap, bytes); | 1481 memmove(&buffer[end], datap, bytes); |
| 1288 end += bytes; | 1482 end += bytes; |
| 1289 datap += bytes; | 1483 datap += bytes; |
| 1290 data_written += bytes; | 1484 data_written += bytes; |
| 1291 provided -= bytes; | 1485 provided -= bytes; |
| 1292 ASSERT(end < start); | 1486 ASSERT(end < start); |
| 1293 } | 1487 } |
| 1294 | 1488 |
| 1295 if (SSL_LOG_DATA) { | 1489 if (SSL_LOG_DATA) { |
| 1296 Log::Print("SSLWriteCallback: provided: %ld, written %ld bytes\n", | 1490 Log::PrintErr("SSLWriteCallback: provided: %ld, written %ld bytes\n", |
| 1297 *data_provided, data_written); | 1491 *data_provided, data_written); |
| 1298 } | 1492 } |
| 1299 | 1493 |
| 1300 filter->SetBufferEnd(kWriteEncrypted, end); | 1494 filter->SetBufferEnd(kWriteEncrypted, end); |
| 1301 *data_provided = data_written; | 1495 *data_provided = data_written; |
| 1302 return (data_written == 0) ? errSSLWouldBlock : noErr; | 1496 return (data_written == 0) ? errSSLWouldBlock : noErr; |
| 1303 } | 1497 } |
| 1304 | 1498 |
| 1305 | 1499 |
| 1306 OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start, | 1500 OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start, |
| 1307 intptr_t end, | 1501 intptr_t end, |
| 1308 intptr_t* bytes_processed) { | 1502 intptr_t* bytes_processed) { |
| 1309 ASSERT(bytes_processed != NULL); | 1503 ASSERT(bytes_processed != NULL); |
| 1310 intptr_t length = end - start; | 1504 intptr_t length = end - start; |
| 1311 OSStatus status = noErr; | 1505 OSStatus status = noErr; |
| 1312 size_t bytes = 0; | 1506 size_t bytes = 0; |
| 1313 if (length > 0) { | 1507 if (length > 0) { |
| 1314 status = SSLWrite( | 1508 status = SSLWrite( |
| 1315 ssl_context_, | 1509 ssl_context_, |
| 1316 reinterpret_cast<void*>(buffers_[kWritePlaintext] + start), | 1510 reinterpret_cast<void*>(buffers_[kWritePlaintext] + start), |
| 1317 length, | 1511 length, |
| 1318 &bytes); | 1512 &bytes); |
| 1319 if (SSL_LOG_STATUS) { | 1513 if (SSL_LOG_STATUS) { |
| 1320 Log::Print("SSLWrite: status = %ld\n", static_cast<intptr_t>(status)); | 1514 Log::PrintErr("SSLWrite: status = %ld\n", static_cast<intptr_t>(status)); |
| 1321 } | 1515 } |
| 1322 if ((status != noErr) && (status != errSSLWouldBlock)) { | 1516 if ((status != noErr) && (status != errSSLWouldBlock)) { |
| 1323 *bytes_processed = 0; | 1517 *bytes_processed = 0; |
| 1324 return status; | 1518 return status; |
| 1325 } | 1519 } |
| 1326 } | 1520 } |
| 1327 if (SSL_LOG_DATA) { | 1521 if (SSL_LOG_DATA) { |
| 1328 Log::Print("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n", | 1522 Log::PrintErr("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n", |
| 1329 length, bytes); | 1523 length, bytes); |
| 1330 } | 1524 } |
| 1331 *bytes_processed = static_cast<intptr_t>(bytes); | 1525 *bytes_processed = static_cast<intptr_t>(bytes); |
| 1332 return status; | 1526 return status; |
| 1333 } | 1527 } |
| 1334 | 1528 |
| 1335 } // namespace bin | 1529 } // namespace bin |
| 1336 } // namespace dart | 1530 } // namespace dart |
| 1337 | 1531 |
| 1338 #endif // TARGET_OS_IOS | 1532 #endif // TARGET_OS_IOS |
| 1339 | 1533 |
| 1340 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1534 #endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| OLD | NEW |