| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED) | 5 #if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if defined(TARGET_OS_ANDROID) || \ | 8 #if defined(TARGET_OS_ANDROID) || \ |
| 9 defined(TARGET_OS_LINUX) || \ | 9 defined(TARGET_OS_LINUX) || \ |
| 10 defined(TARGET_OS_WINDOWS) | 10 defined(TARGET_OS_WINDOWS) |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 | 89 |
| 90 | 90 |
| 91 /* Handle an error reported from the BoringSSL library. */ | 91 /* Handle an error reported from the BoringSSL library. */ |
| 92 static void ThrowIOException(int status, | 92 static void ThrowIOException(int status, |
| 93 const char* exception_type, | 93 const char* exception_type, |
| 94 const char* message) { | 94 const char* message) { |
| 95 char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE]; | 95 char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE]; |
| 96 FetchErrorString(error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE); | 96 FetchErrorString(error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE); |
| 97 OSError os_error_struct(status, error_string, OSError::kBoringSSL); | 97 Dart_Handle exception; |
| 98 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); | 98 { |
| 99 Dart_Handle exception = | 99 OSError os_error_struct(status, error_string, OSError::kBoringSSL); |
| 100 DartUtils::NewDartIOException(exception_type, message, os_error); | 100 Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); |
| 101 ASSERT(!Dart_IsError(exception)); | 101 exception = |
| 102 DartUtils::NewDartIOException(exception_type, message, os_error); |
| 103 ASSERT(!Dart_IsError(exception)); |
| 104 } |
| 102 Dart_ThrowException(exception); | 105 Dart_ThrowException(exception); |
| 103 UNREACHABLE(); | 106 UNREACHABLE(); |
| 104 } | 107 } |
| 105 | 108 |
| 106 | 109 |
| 107 static SSLFilter* GetFilter(Dart_NativeArguments args) { | 110 static SSLFilter* GetFilter(Dart_NativeArguments args) { |
| 108 SSLFilter* filter; | 111 SSLFilter* filter; |
| 109 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | 112 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 110 ASSERT(Dart_IsInstance(dart_this)); | 113 ASSERT(Dart_IsInstance(dart_this)); |
| 111 ThrowIfError(Dart_GetNativeInstanceField( | 114 ThrowIfError(Dart_GetNativeInstanceField( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 136 reinterpret_cast<intptr_t>(filter)); | 139 reinterpret_cast<intptr_t>(filter)); |
| 137 RETURN_IF_ERROR(err); | 140 RETURN_IF_ERROR(err); |
| 138 Dart_NewWeakPersistentHandle(dart_this, | 141 Dart_NewWeakPersistentHandle(dart_this, |
| 139 reinterpret_cast<void*>(filter), | 142 reinterpret_cast<void*>(filter), |
| 140 sizeof(*filter), | 143 sizeof(*filter), |
| 141 DeleteFilter); | 144 DeleteFilter); |
| 142 return Dart_Null(); | 145 return Dart_Null(); |
| 143 } | 146 } |
| 144 | 147 |
| 145 | 148 |
| 146 static SSL_CTX* GetSecurityContext(Dart_NativeArguments args) { | 149 static SSLContext* GetSecurityContext(Dart_NativeArguments args) { |
| 147 SSL_CTX* context; | 150 SSLContext* context; |
| 148 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | 151 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 149 ASSERT(Dart_IsInstance(dart_this)); | 152 ASSERT(Dart_IsInstance(dart_this)); |
| 150 ThrowIfError(Dart_GetNativeInstanceField( | 153 ThrowIfError(Dart_GetNativeInstanceField( |
| 151 dart_this, | 154 dart_this, |
| 152 kSecurityContextNativeFieldIndex, | 155 kSecurityContextNativeFieldIndex, |
| 153 reinterpret_cast<intptr_t*>(&context))); | 156 reinterpret_cast<intptr_t*>(&context))); |
| 154 return context; | 157 return context; |
| 155 } | 158 } |
| 156 | 159 |
| 157 | 160 |
| 158 static void FreeSecurityContext( | 161 static void DeleteSecurityContext( |
| 159 void* isolate_data, | 162 void* isolate_data, |
| 160 Dart_WeakPersistentHandle handle, | 163 Dart_WeakPersistentHandle handle, |
| 161 void* context_pointer) { | 164 void* context_pointer) { |
| 162 SSL_CTX* context = static_cast<SSL_CTX*>(context_pointer); | 165 SSLContext* context = static_cast<SSLContext*>(context_pointer); |
| 163 SSL_CTX_free(context); | 166 delete context; |
| 164 } | 167 } |
| 165 | 168 |
| 166 | 169 |
| 167 static Dart_Handle SetSecurityContext(Dart_NativeArguments args, | 170 static Dart_Handle SetSecurityContext(Dart_NativeArguments args, |
| 168 SSL_CTX* context) { | 171 SSLContext* context) { |
| 169 const int approximate_size_of_context = 1500; | 172 const int approximate_size_of_context = 1500; |
| 170 Dart_Handle dart_this = Dart_GetNativeArgument(args, 0); | 173 Dart_Handle dart_this = Dart_GetNativeArgument(args, 0); |
| 171 RETURN_IF_ERROR(dart_this); | 174 RETURN_IF_ERROR(dart_this); |
| 172 ASSERT(Dart_IsInstance(dart_this)); | 175 ASSERT(Dart_IsInstance(dart_this)); |
| 173 Dart_Handle err = Dart_SetNativeInstanceField( | 176 Dart_Handle err = Dart_SetNativeInstanceField( |
| 174 dart_this, | 177 dart_this, |
| 175 kSecurityContextNativeFieldIndex, | 178 kSecurityContextNativeFieldIndex, |
| 176 reinterpret_cast<intptr_t>(context)); | 179 reinterpret_cast<intptr_t>(context)); |
| 177 RETURN_IF_ERROR(err); | 180 RETURN_IF_ERROR(err); |
| 178 Dart_NewWeakPersistentHandle(dart_this, | 181 Dart_NewWeakPersistentHandle(dart_this, |
| 179 context, | 182 context, |
| 180 approximate_size_of_context, | 183 approximate_size_of_context, |
| 181 FreeSecurityContext); | 184 DeleteSecurityContext); |
| 182 return Dart_Null(); | 185 return Dart_Null(); |
| 183 } | 186 } |
| 184 | 187 |
| 185 | 188 |
| 186 static X509* GetX509Certificate(Dart_NativeArguments args) { | 189 static X509* GetX509Certificate(Dart_NativeArguments args) { |
| 187 X509* certificate; | 190 X509* certificate; |
| 188 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | 191 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 189 ASSERT(Dart_IsInstance(dart_this)); | 192 ASSERT(Dart_IsInstance(dart_this)); |
| 190 ThrowIfError(Dart_GetNativeInstanceField( | 193 ThrowIfError(Dart_GetNativeInstanceField( |
| 191 dart_this, | 194 dart_this, |
| 192 kX509NativeFieldIndex, | 195 kX509NativeFieldIndex, |
| 193 reinterpret_cast<intptr_t*>(&certificate))); | 196 reinterpret_cast<intptr_t*>(&certificate))); |
| 194 return certificate; | 197 return certificate; |
| 195 } | 198 } |
| 196 | 199 |
| 197 | 200 |
| 198 // Forward declaration. | 201 // Forward declaration. |
| 199 static void SetAlpnProtocolList(Dart_Handle protocols_handle, | 202 static void SetAlpnProtocolList(Dart_Handle protocols_handle, |
| 200 SSL* ssl, | 203 SSL* ssl, |
| 201 SSL_CTX* context, | 204 SSLContext* context, |
| 202 bool is_server); | 205 bool is_server); |
| 203 | 206 |
| 204 | 207 |
| 205 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { | 208 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { |
| 206 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); | 209 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 207 SSLFilter* filter = new SSLFilter(); | 210 SSLFilter* filter = new SSLFilter(); |
| 208 Dart_Handle err = SetFilter(args, filter); | 211 Dart_Handle err = SetFilter(args, filter); |
| 209 if (Dart_IsError(err)) { | 212 if (Dart_IsError(err)) { |
| 210 filter->Release(); | 213 filter->Release(); |
| 211 Dart_PropagateError(err); | 214 Dart_PropagateError(err); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 228 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); | 231 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); |
| 229 bool require_client_certificate = | 232 bool require_client_certificate = |
| 230 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5)); | 233 DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5)); |
| 231 Dart_Handle protocols_handle = | 234 Dart_Handle protocols_handle = |
| 232 ThrowIfError(Dart_GetNativeArgument(args, 6)); | 235 ThrowIfError(Dart_GetNativeArgument(args, 6)); |
| 233 | 236 |
| 234 const char* host_name = NULL; | 237 const char* host_name = NULL; |
| 235 // TODO(whesse): Is truncating a Dart string containing \0 what we want? | 238 // TODO(whesse): Is truncating a Dart string containing \0 what we want? |
| 236 ThrowIfError(Dart_StringToCString(host_name_object, &host_name)); | 239 ThrowIfError(Dart_StringToCString(host_name_object, &host_name)); |
| 237 | 240 |
| 238 SSL_CTX* context = NULL; | 241 SSLContext* context = NULL; |
| 239 if (!Dart_IsNull(context_object)) { | 242 if (!Dart_IsNull(context_object)) { |
| 240 ThrowIfError(Dart_GetNativeInstanceField( | 243 ThrowIfError(Dart_GetNativeInstanceField( |
| 241 context_object, | 244 context_object, |
| 242 kSecurityContextNativeFieldIndex, | 245 kSecurityContextNativeFieldIndex, |
| 243 reinterpret_cast<intptr_t*>(&context))); | 246 reinterpret_cast<intptr_t*>(&context))); |
| 244 } | 247 } |
| 245 | 248 |
| 246 // The protocols_handle is guaranteed to be a valid Uint8List. | 249 // The protocols_handle is guaranteed to be a valid Uint8List. |
| 247 // It will have the correct length encoding of the protocols array. | 250 // It will have the correct length encoding of the protocols array. |
| 248 ASSERT(!Dart_IsNull(protocols_handle)); | 251 ASSERT(!Dart_IsNull(protocols_handle)); |
| 249 | 252 |
| 250 GetFilter(args)->Connect(host_name, | 253 GetFilter(args)->Connect(host_name, |
| 251 context, | 254 context->context(), |
| 252 is_server, | 255 is_server, |
| 253 request_client_certificate, | 256 request_client_certificate, |
| 254 require_client_certificate, | 257 require_client_certificate, |
| 255 protocols_handle); | 258 protocols_handle); |
| 256 } | 259 } |
| 257 | 260 |
| 258 | 261 |
| 259 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) { | 262 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) { |
| 260 SSLFilter* filter = GetFilter(args); | 263 SSLFilter* filter = GetFilter(args); |
| 261 // The SSLFilter is deleted in the finalizer for the Dart object created by | 264 // The SSLFilter is deleted in the finalizer for the Dart object created by |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 if (Dart_IsError(result)) { | 422 if (Dart_IsError(result)) { |
| 420 filter->callback_error = result; | 423 filter->callback_error = result; |
| 421 return 0; | 424 return 0; |
| 422 } | 425 } |
| 423 return DartUtils::GetBooleanValue(result); | 426 return DartUtils::GetBooleanValue(result); |
| 424 } | 427 } |
| 425 | 428 |
| 426 | 429 |
| 427 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { | 430 void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { |
| 428 SSLFilter::InitializeLibrary(); | 431 SSLFilter::InitializeLibrary(); |
| 429 SSL_CTX* context = SSL_CTX_new(TLS_method()); | 432 SSL_CTX* ctx = SSL_CTX_new(TLS_method()); |
| 430 SSL_CTX_set_verify(context, SSL_VERIFY_PEER, CertificateCallback); | 433 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, CertificateCallback); |
| 431 SSL_CTX_set_min_version(context, TLS1_VERSION); | 434 SSL_CTX_set_min_version(ctx, TLS1_VERSION); |
| 432 SSL_CTX_set_cipher_list(context, "HIGH:MEDIUM"); | 435 SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM"); |
| 433 SSL_CTX_set_cipher_list_tls11(context, "HIGH:MEDIUM"); | 436 SSL_CTX_set_cipher_list_tls11(ctx, "HIGH:MEDIUM"); |
| 437 SSLContext* context = new SSLContext(ctx); |
| 434 Dart_Handle err = SetSecurityContext(args, context); | 438 Dart_Handle err = SetSecurityContext(args, context); |
| 435 if (Dart_IsError(err)) { | 439 if (Dart_IsError(err)) { |
| 436 SSL_CTX_free(context); | 440 delete context; |
| 437 Dart_PropagateError(err); | 441 Dart_PropagateError(err); |
| 438 } | 442 } |
| 439 } | 443 } |
| 440 | 444 |
| 441 | 445 |
| 442 int PasswordCallback(char* buf, int size, int rwflag, void* userdata) { | 446 int PasswordCallback(char* buf, int size, int rwflag, void* userdata) { |
| 443 char* password = static_cast<char*>(userdata); | 447 char* password = static_cast<char*>(userdata); |
| 444 ASSERT(size == PEM_BUFSIZE); | 448 ASSERT(size == PEM_BUFSIZE); |
| 445 strncpy(buf, password, size); | 449 strncpy(buf, password, size); |
| 446 return strlen(password); | 450 return strlen(password); |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 } else { | 660 } else { |
| 657 Dart_ThrowException(DartUtils::NewDartArgumentError( | 661 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 658 "Password is not a String or null")); | 662 "Password is not a String or null")); |
| 659 } | 663 } |
| 660 return password; | 664 return password; |
| 661 } | 665 } |
| 662 | 666 |
| 663 | 667 |
| 664 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 668 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
| 665 Dart_NativeArguments args) { | 669 Dart_NativeArguments args) { |
| 666 SSL_CTX* context = GetSecurityContext(args); | 670 SSLContext* context = GetSecurityContext(args); |
| 667 const char* password = GetPasswordArgument(args, 2); | 671 const char* password = GetPasswordArgument(args, 2); |
| 668 | 672 |
| 669 int status; | 673 int status; |
| 670 { | 674 { |
| 671 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 675 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 672 EVP_PKEY *key = GetPrivateKey(bio.bio(), password); | 676 EVP_PKEY *key = GetPrivateKey(bio.bio(), password); |
| 673 status = SSL_CTX_use_PrivateKey(context, key); | 677 status = SSL_CTX_use_PrivateKey(context->context(), key); |
| 678 // SSL_CTX_use_PrivateKey increments the reference count of key on success, |
| 679 // so we have to call EVP_PKEY_free on both success and failure. |
| 680 EVP_PKEY_free(key); |
| 674 } | 681 } |
| 675 | 682 |
| 676 // TODO(24184): Handle different expected errors here - file missing, | 683 // TODO(24184): Handle different expected errors here - file missing, |
| 677 // incorrect password, file not a PEM, and throw exceptions. | 684 // incorrect password, file not a PEM, and throw exceptions. |
| 678 // CheckStatus should also throw an exception in uncaught cases. | 685 // CheckStatus should also throw an exception in uncaught cases. |
| 679 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); | 686 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); |
| 680 } | 687 } |
| 681 | 688 |
| 682 | 689 |
| 683 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, | 690 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, |
| 684 BIO* bio, | 691 BIO* bio, |
| 685 const char* password) { | 692 const char* password) { |
| 686 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 693 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
| 687 if (p12.get() == NULL) { | 694 if (p12.get() == NULL) { |
| 688 return 0; | 695 return 0; |
| 689 } | 696 } |
| 690 | 697 |
| 691 EVP_PKEY* key = NULL; | 698 EVP_PKEY* key = NULL; |
| 692 X509 *cert = NULL; | 699 X509 *cert = NULL; |
| 693 STACK_OF(X509) *ca_certs = NULL; | 700 STACK_OF(X509) *ca_certs = NULL; |
| 694 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); | 701 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
| 695 if (status == 0) { | 702 if (status == 0) { |
| 696 return status; | 703 return status; |
| 697 } | 704 } |
| 698 | 705 |
| 699 ScopedX509Stack cert_stack(ca_certs); | 706 ScopedX509Stack cert_stack(ca_certs); |
| 700 X509_STORE* store = SSL_CTX_get_cert_store(context); | 707 X509_STORE* store = SSL_CTX_get_cert_store(context); |
| 701 status = X509_STORE_add_cert(store, cert); | 708 status = X509_STORE_add_cert(store, cert); |
| 709 // X509_STORE_add_cert increments the reference count of cert on success. |
| 710 X509_free(cert); |
| 702 if (status == 0) { | 711 if (status == 0) { |
| 703 X509_free(cert); | |
| 704 return status; | 712 return status; |
| 705 } | 713 } |
| 706 | 714 |
| 707 X509* ca; | 715 X509* ca; |
| 708 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { | 716 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
| 709 status = X509_STORE_add_cert(store, ca); | 717 status = X509_STORE_add_cert(store, ca); |
| 718 // X509_STORE_add_cert increments the reference count of cert on success. |
| 719 X509_free(ca); |
| 710 if (status == 0) { | 720 if (status == 0) { |
| 711 X509_free(ca); | |
| 712 return status; | 721 return status; |
| 713 } | 722 } |
| 714 } | 723 } |
| 715 | 724 |
| 716 return status; | 725 return status; |
| 717 } | 726 } |
| 718 | 727 |
| 719 | 728 |
| 720 static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) { | 729 static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) { |
| 721 X509_STORE* store = SSL_CTX_get_cert_store(context); | 730 X509_STORE* store = SSL_CTX_get_cert_store(context); |
| 722 | 731 |
| 723 int status = 0; | 732 int status = 0; |
| 724 X509* cert = NULL; | 733 X509* cert = NULL; |
| 725 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { | 734 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 726 status = X509_STORE_add_cert(store, cert); | 735 status = X509_STORE_add_cert(store, cert); |
| 736 // X509_STORE_add_cert increments the reference count of cert on success. |
| 737 X509_free(cert); |
| 727 if (status == 0) { | 738 if (status == 0) { |
| 728 X509_free(cert); | |
| 729 return status; | 739 return status; |
| 730 } | 740 } |
| 731 } | 741 } |
| 732 | 742 |
| 733 // If no PEM start line is found, it means that we read to the end of the | 743 // If no PEM start line is found, it means that we read to the end of the |
| 734 // file, or that the file isn't PEM. In the first case, status will be | 744 // file, or that the file isn't PEM. In the first case, status will be |
| 735 // non-zero indicating success. In the second case, status will be 0, | 745 // non-zero indicating success. In the second case, status will be 0, |
| 736 // indicating that we should try to read as PKCS12. If there is some other | 746 // indicating that we should try to read as PKCS12. If there is some other |
| 737 // error, we return it up to the caller. | 747 // error, we return it up to the caller. |
| 738 return NoPEMStartLine() ? status : 0; | 748 return NoPEMStartLine() ? status : 0; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 752 } else { | 762 } else { |
| 753 // The PEM file was successfully parsed. | 763 // The PEM file was successfully parsed. |
| 754 ERR_clear_error(); | 764 ERR_clear_error(); |
| 755 } | 765 } |
| 756 return status; | 766 return status; |
| 757 } | 767 } |
| 758 | 768 |
| 759 | 769 |
| 760 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 770 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
| 761 Dart_NativeArguments args) { | 771 Dart_NativeArguments args) { |
| 762 SSL_CTX* context = GetSecurityContext(args); | 772 SSLContext* context = GetSecurityContext(args); |
| 763 const char* password = GetPasswordArgument(args, 2); | 773 const char* password = GetPasswordArgument(args, 2); |
| 764 int status; | 774 int status; |
| 765 { | 775 { |
| 766 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 776 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 767 status = SetTrustedCertificatesBytes(context, bio.bio(), password); | 777 status = SetTrustedCertificatesBytes( |
| 778 context->context(), bio.bio(), password); |
| 768 } | 779 } |
| 769 CheckStatus(status, | 780 CheckStatus(status, |
| 770 "TlsException", | 781 "TlsException", |
| 771 "Failure in setTrustedCertificatesBytes"); | 782 "Failure in setTrustedCertificatesBytes"); |
| 772 } | 783 } |
| 773 | 784 |
| 774 | 785 |
| 775 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { | 786 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { |
| 776 Dart_SetReturnValue(args, Dart_NewBoolean(true)); | 787 Dart_SetReturnValue(args, Dart_NewBoolean(true)); |
| 777 } | 788 } |
| 778 | 789 |
| 779 | 790 |
| 780 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 791 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
| 781 Dart_NativeArguments args) { | 792 Dart_NativeArguments args) { |
| 782 SSL_CTX* context = GetSecurityContext(args); | 793 SSLContext* context = GetSecurityContext(args); |
| 783 #if defined(TARGET_OS_ANDROID) | 794 #if defined(TARGET_OS_ANDROID) |
| 784 // On Android, we don't compile in the trusted root certificates. Insead, | 795 // On Android, we don't compile in the trusted root certificates. Insead, |
| 785 // we use the directory of trusted certificates already present on the device. | 796 // we use the directory of trusted certificates already present on the device. |
| 786 // This saves ~240KB from the size of the binary. This has the drawback that | 797 // This saves ~240KB from the size of the binary. This has the drawback that |
| 787 // SSL_do_handshake will synchronously hit the filesystem looking for root | 798 // SSL_do_handshake will synchronously hit the filesystem looking for root |
| 788 // certs during its trust evaluation. We call SSL_do_handshake directly from | 799 // certs during its trust evaluation. We call SSL_do_handshake directly from |
| 789 // the Dart thread so that Dart code can be invoked from the "bad certificate" | 800 // the Dart thread so that Dart code can be invoked from the "bad certificate" |
| 790 // callback called by SSL_do_handshake. | 801 // callback called by SSL_do_handshake. |
| 791 const char* android_cacerts = "/system/etc/security/cacerts"; | 802 const char* android_cacerts = "/system/etc/security/cacerts"; |
| 792 int status = SSL_CTX_load_verify_locations(context, NULL, android_cacerts); | 803 int status = SSL_CTX_load_verify_locations( |
| 804 context->context(), NULL, android_cacerts); |
| 793 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); | 805 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); |
| 794 #else | 806 #else |
| 795 X509_STORE* store = SSL_CTX_get_cert_store(context); | 807 X509_STORE* store = SSL_CTX_get_cert_store(context->context()); |
| 796 BIO* roots_bio = | 808 BIO* roots_bio = |
| 797 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), | 809 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), |
| 798 root_certificates_pem_length); | 810 root_certificates_pem_length); |
| 799 X509* root_cert; | 811 X509* root_cert; |
| 800 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, | 812 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, |
| 801 // backed by a memory buffer), and returns X509 objects, one by one. | 813 // backed by a memory buffer), and returns X509 objects, one by one. |
| 802 // When the end of the bio is reached, it returns null. | 814 // When the end of the bio is reached, it returns null. |
| 803 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) { | 815 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) { |
| 804 X509_STORE_add_cert(store, root_cert); | 816 int status = X509_STORE_add_cert(store, root_cert); |
| 817 // X509_STORE_add_cert increments the reference count of cert on success. |
| 818 X509_free(root_cert); |
| 819 if (status == 0) { |
| 820 break; |
| 821 } |
| 805 } | 822 } |
| 806 BIO_free(roots_bio); | 823 BIO_free(roots_bio); |
| 807 // If there is an error here, it must be the error indicating that we are done | 824 // If there is an error here, it must be the error indicating that we are done |
| 808 // reading PEM certificates. | 825 // reading PEM certificates. |
| 809 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); | 826 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); |
| 810 ERR_clear_error(); | 827 ERR_clear_error(); |
| 811 #endif // defined(TARGET_OS_ANDROID) | 828 #endif // defined(TARGET_OS_ANDROID) |
| 812 } | 829 } |
| 813 | 830 |
| 814 | 831 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 837 } | 854 } |
| 838 if (status == 0) { | 855 if (status == 0) { |
| 839 return status; | 856 return status; |
| 840 } | 857 } |
| 841 | 858 |
| 842 SSL_CTX_clear_chain_certs(context); | 859 SSL_CTX_clear_chain_certs(context); |
| 843 | 860 |
| 844 X509* ca; | 861 X509* ca; |
| 845 while ((ca = sk_X509_shift(certs.get())) != NULL) { | 862 while ((ca = sk_X509_shift(certs.get())) != NULL) { |
| 846 status = SSL_CTX_add0_chain_cert(context, ca); | 863 status = SSL_CTX_add0_chain_cert(context, ca); |
| 864 // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the |
| 865 // call fails. |
| 847 if (status == 0) { | 866 if (status == 0) { |
| 848 X509_free(ca); | 867 X509_free(ca); |
| 849 return status; | 868 return status; |
| 850 } | 869 } |
| 851 } | 870 } |
| 852 | 871 |
| 853 return status; | 872 return status; |
| 854 } | 873 } |
| 855 | 874 |
| 856 | 875 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 868 } | 887 } |
| 869 if (status == 0) { | 888 if (status == 0) { |
| 870 return status; | 889 return status; |
| 871 } | 890 } |
| 872 | 891 |
| 873 SSL_CTX_clear_chain_certs(context); | 892 SSL_CTX_clear_chain_certs(context); |
| 874 | 893 |
| 875 X509* ca; | 894 X509* ca; |
| 876 while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { | 895 while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 877 status = SSL_CTX_add0_chain_cert(context, ca); | 896 status = SSL_CTX_add0_chain_cert(context, ca); |
| 897 // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the |
| 898 // call fails. |
| 878 if (status == 0) { | 899 if (status == 0) { |
| 879 X509_free(ca); | 900 X509_free(ca); |
| 880 return status; | 901 return status; |
| 881 } | 902 } |
| 882 // Note that we must not free `ca` if it was successfully added to the | 903 // Note that we must not free `ca` if it was successfully added to the |
| 883 // chain. We must free the main certificate x509, though since its reference | 904 // chain. We must free the main certificate x509, though since its reference |
| 884 // count is increased by SSL_CTX_use_certificate. | 905 // count is increased by SSL_CTX_use_certificate. |
| 885 } | 906 } |
| 886 | 907 |
| 887 return NoPEMStartLine() ? status : 0; | 908 return NoPEMStartLine() ? status : 0; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 899 } else { | 920 } else { |
| 900 // The PEM file was successfully read. | 921 // The PEM file was successfully read. |
| 901 ERR_clear_error(); | 922 ERR_clear_error(); |
| 902 } | 923 } |
| 903 return status; | 924 return status; |
| 904 } | 925 } |
| 905 | 926 |
| 906 | 927 |
| 907 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 928 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
| 908 Dart_NativeArguments args) { | 929 Dart_NativeArguments args) { |
| 909 SSL_CTX* context = GetSecurityContext(args); | 930 SSLContext* context = GetSecurityContext(args); |
| 910 const char* password = GetPasswordArgument(args, 2); | 931 const char* password = GetPasswordArgument(args, 2); |
| 911 int status; | 932 int status; |
| 912 { | 933 { |
| 913 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 934 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 914 status = UseChainBytes(context, bio.bio(), password); | 935 status = UseChainBytes(context->context(), bio.bio(), password); |
| 915 } | 936 } |
| 916 CheckStatus(status, | 937 CheckStatus(status, |
| 917 "TlsException", | 938 "TlsException", |
| 918 "Failure in useCertificateChainBytes"); | 939 "Failure in useCertificateChainBytes"); |
| 919 } | 940 } |
| 920 | 941 |
| 921 | 942 |
| 922 static int SetClientAuthoritiesPKCS12(SSL_CTX* context, | 943 static int SetClientAuthoritiesPKCS12(SSL_CTX* context, |
| 923 BIO* bio, | 944 BIO* bio, |
| 924 const char* password) { | 945 const char* password) { |
| 925 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 946 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
| 926 if (p12.get() == NULL) { | 947 if (p12.get() == NULL) { |
| 927 return 0; | 948 return 0; |
| 928 } | 949 } |
| 929 | 950 |
| 930 EVP_PKEY* key = NULL; | 951 EVP_PKEY* key = NULL; |
| 931 X509 *cert = NULL; | 952 X509 *cert = NULL; |
| 932 STACK_OF(X509) *ca_certs = NULL; | 953 STACK_OF(X509) *ca_certs = NULL; |
| 933 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); | 954 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
| 934 if (status == 0) { | 955 if (status == 0) { |
| 935 return status; | 956 return status; |
| 936 } | 957 } |
| 937 | 958 |
| 938 ScopedX509Stack cert_stack(ca_certs); | 959 ScopedX509Stack cert_stack(ca_certs); |
| 939 status = SSL_CTX_add_client_CA(context, cert); | 960 status = SSL_CTX_add_client_CA(context, cert); |
| 961 // SSL_CTX_add_client_CA increments the reference count of cert on success. |
| 962 X509_free(cert); |
| 940 if (status == 0) { | 963 if (status == 0) { |
| 941 X509_free(cert); | |
| 942 return status; | 964 return status; |
| 943 } | 965 } |
| 944 | 966 |
| 945 X509* ca; | 967 X509* ca; |
| 946 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { | 968 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
| 947 status = SSL_CTX_add_client_CA(context, ca); | 969 status = SSL_CTX_add_client_CA(context, ca); |
| 970 // SSL_CTX_add_client_CA increments the reference count of ca on success. |
| 948 X509_free(ca); // The name has been extracted. | 971 X509_free(ca); // The name has been extracted. |
| 949 if (status == 0) { | 972 if (status == 0) { |
| 950 return status; | 973 return status; |
| 951 } | 974 } |
| 952 } | 975 } |
| 953 | 976 |
| 954 return status; | 977 return status; |
| 955 } | 978 } |
| 956 | 979 |
| 957 | 980 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 982 } else { | 1005 } else { |
| 983 // The PEM file was successfully parsed. | 1006 // The PEM file was successfully parsed. |
| 984 ERR_clear_error(); | 1007 ERR_clear_error(); |
| 985 } | 1008 } |
| 986 return status; | 1009 return status; |
| 987 } | 1010 } |
| 988 | 1011 |
| 989 | 1012 |
| 990 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 1013 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
| 991 Dart_NativeArguments args) { | 1014 Dart_NativeArguments args) { |
| 992 SSL_CTX* context = GetSecurityContext(args); | 1015 SSLContext* context = GetSecurityContext(args); |
| 993 const char* password = GetPasswordArgument(args, 2); | 1016 const char* password = GetPasswordArgument(args, 2); |
| 994 | 1017 |
| 995 int status; | 1018 int status; |
| 996 { | 1019 { |
| 997 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 1020 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 998 status = SetClientAuthorities(context, bio.bio(), password); | 1021 status = SetClientAuthorities(context->context(), bio.bio(), password); |
| 999 } | 1022 } |
| 1000 | 1023 |
| 1001 CheckStatus(status, | 1024 CheckStatus(status, |
| 1002 "TlsException", | 1025 "TlsException", |
| 1003 "Failure in setClientAuthoritiesBytes"); | 1026 "Failure in setClientAuthoritiesBytes"); |
| 1004 } | 1027 } |
| 1005 | 1028 |
| 1006 | 1029 |
| 1007 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( | 1030 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( |
| 1008 Dart_NativeArguments args) { | 1031 Dart_NativeArguments args) { |
| 1009 SSL_CTX* context = GetSecurityContext(args); | 1032 SSLContext* context = GetSecurityContext(args); |
| 1010 Dart_Handle protocols_handle = | 1033 Dart_Handle protocols_handle = |
| 1011 ThrowIfError(Dart_GetNativeArgument(args, 1)); | 1034 ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| 1012 Dart_Handle is_server_handle = | 1035 Dart_Handle is_server_handle = |
| 1013 ThrowIfError(Dart_GetNativeArgument(args, 2)); | 1036 ThrowIfError(Dart_GetNativeArgument(args, 2)); |
| 1014 if (Dart_IsBoolean(is_server_handle)) { | 1037 if (Dart_IsBoolean(is_server_handle)) { |
| 1015 bool is_server = DartUtils::GetBooleanValue(is_server_handle); | 1038 bool is_server = DartUtils::GetBooleanValue(is_server_handle); |
| 1016 SetAlpnProtocolList(protocols_handle, NULL, context, is_server); | 1039 SetAlpnProtocolList(protocols_handle, NULL, context, is_server); |
| 1017 } else { | 1040 } else { |
| 1018 Dart_ThrowException(DartUtils::NewDartArgumentError( | 1041 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 1019 "Non-boolean is_server argument passed to SetAlpnProtocols")); | 1042 "Non-boolean is_server argument passed to SetAlpnProtocols")); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 server_list += protocol_length; | 1379 server_list += protocol_length; |
| 1357 } | 1380 } |
| 1358 // TODO(23580): Make failure send a fatal alert instead of ignoring ALPN. | 1381 // TODO(23580): Make failure send a fatal alert instead of ignoring ALPN. |
| 1359 return SSL_TLSEXT_ERR_NOACK; | 1382 return SSL_TLSEXT_ERR_NOACK; |
| 1360 } | 1383 } |
| 1361 | 1384 |
| 1362 | 1385 |
| 1363 // Sets the protocol list for ALPN on a SSL object or a context. | 1386 // Sets the protocol list for ALPN on a SSL object or a context. |
| 1364 static void SetAlpnProtocolList(Dart_Handle protocols_handle, | 1387 static void SetAlpnProtocolList(Dart_Handle protocols_handle, |
| 1365 SSL* ssl, | 1388 SSL* ssl, |
| 1366 SSL_CTX* context, | 1389 SSLContext* context, |
| 1367 bool is_server) { | 1390 bool is_server) { |
| 1368 // Enable ALPN (application layer protocol negotiation) if the caller provides | 1391 // Enable ALPN (application layer protocol negotiation) if the caller provides |
| 1369 // a valid list of supported protocols. | 1392 // a valid list of supported protocols. |
| 1370 Dart_TypedData_Type protocols_type; | 1393 Dart_TypedData_Type protocols_type; |
| 1371 uint8_t* protocol_string = NULL; | 1394 uint8_t* protocol_string = NULL; |
| 1372 uint8_t* protocol_string_copy = NULL; | 1395 uint8_t* protocol_string_copy = NULL; |
| 1373 intptr_t protocol_string_len = 0; | 1396 intptr_t protocol_string_len = 0; |
| 1374 int status; | 1397 int status; |
| 1375 | 1398 |
| 1376 Dart_Handle result = Dart_TypedDataAcquireData( | 1399 Dart_Handle result = Dart_TypedDataAcquireData( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1393 // ALPN on server connections must be set on an SSL_CTX object, | 1416 // ALPN on server connections must be set on an SSL_CTX object, |
| 1394 // not on the SSL object of the individual connection. | 1417 // not on the SSL object of the individual connection. |
| 1395 ASSERT(context != NULL); | 1418 ASSERT(context != NULL); |
| 1396 ASSERT(ssl == NULL); | 1419 ASSERT(ssl == NULL); |
| 1397 // Because it must be passed as a single void*, terminate | 1420 // Because it must be passed as a single void*, terminate |
| 1398 // the list of (length, data) strings with a length 0 string. | 1421 // the list of (length, data) strings with a length 0 string. |
| 1399 protocol_string_copy = | 1422 protocol_string_copy = |
| 1400 static_cast<uint8_t*>(malloc(protocol_string_len + 1)); | 1423 static_cast<uint8_t*>(malloc(protocol_string_len + 1)); |
| 1401 memmove(protocol_string_copy, protocol_string, protocol_string_len); | 1424 memmove(protocol_string_copy, protocol_string, protocol_string_len); |
| 1402 protocol_string_copy[protocol_string_len] = '\0'; | 1425 protocol_string_copy[protocol_string_len] = '\0'; |
| 1403 SSL_CTX_set_alpn_select_cb(context, AlpnCallback, protocol_string_copy); | 1426 SSL_CTX_set_alpn_select_cb( |
| 1404 // TODO(whesse): If this function is called again, free the previous | 1427 context->context(), AlpnCallback, protocol_string_copy); |
| 1405 // protocol_string_copy. It may be better to keep this as a native | 1428 context->set_alpn_protocol_string(protocol_string_copy); |
| 1406 // field on the Dart object, since fetching it from the structure is | |
| 1407 // not in the public api. | |
| 1408 // Also free protocol_string_copy when the context is destroyed, | |
| 1409 // in FreeSecurityContext() | |
| 1410 } else { | 1429 } else { |
| 1411 // The function makes a local copy of protocol_string, which it owns. | 1430 // The function makes a local copy of protocol_string, which it owns. |
| 1412 if (ssl != NULL) { | 1431 if (ssl != NULL) { |
| 1413 ASSERT(context == NULL); | 1432 ASSERT(context == NULL); |
| 1414 status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len); | 1433 status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len); |
| 1415 } else { | 1434 } else { |
| 1416 ASSERT(context != NULL); | 1435 ASSERT(context != NULL); |
| 1417 ASSERT(ssl == NULL); | 1436 ASSERT(ssl == NULL); |
| 1418 status = SSL_CTX_set_alpn_protos( | 1437 status = SSL_CTX_set_alpn_protos( |
| 1419 context, protocol_string, protocol_string_len); | 1438 context->context(), protocol_string, protocol_string_len); |
| 1420 } | 1439 } |
| 1421 ASSERT(status == 0); // The function returns a non-standard status. | 1440 ASSERT(status == 0); // The function returns a non-standard status. |
| 1422 } | 1441 } |
| 1423 } | 1442 } |
| 1424 Dart_TypedDataReleaseData(protocols_handle); | 1443 Dart_TypedDataReleaseData(protocols_handle); |
| 1425 } | 1444 } |
| 1426 | 1445 |
| 1427 | 1446 |
| 1428 void SSLFilter::Connect(const char* hostname, | 1447 void SSLFilter::Connect(const char* hostname, |
| 1429 SSL_CTX* context, | 1448 SSL_CTX* context, |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1688 return bytes_processed; | 1707 return bytes_processed; |
| 1689 } | 1708 } |
| 1690 | 1709 |
| 1691 } // namespace bin | 1710 } // namespace bin |
| 1692 } // namespace dart | 1711 } // namespace dart |
| 1693 | 1712 |
| 1694 #endif // defined(TARGET_OS_LINUX) | 1713 #endif // defined(TARGET_OS_LINUX) |
| 1695 | 1714 |
| 1696 #endif // !defined(DART_IO_DISABLED) && | 1715 #endif // !defined(DART_IO_DISABLED) && |
| 1697 // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1716 // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| OLD | NEW |