Chromium Code Reviews| 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 EVP_PKEY_free(key); | |
| 674 } | 679 } |
| 675 | 680 |
| 676 // TODO(24184): Handle different expected errors here - file missing, | 681 // TODO(24184): Handle different expected errors here - file missing, |
| 677 // incorrect password, file not a PEM, and throw exceptions. | 682 // incorrect password, file not a PEM, and throw exceptions. |
| 678 // CheckStatus should also throw an exception in uncaught cases. | 683 // CheckStatus should also throw an exception in uncaught cases. |
| 679 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); | 684 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); |
| 680 } | 685 } |
| 681 | 686 |
| 682 | 687 |
| 683 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, | 688 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, |
| 684 BIO* bio, | 689 BIO* bio, |
| 685 const char* password) { | 690 const char* password) { |
| 686 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 691 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
| 687 if (p12.get() == NULL) { | 692 if (p12.get() == NULL) { |
| 688 return 0; | 693 return 0; |
| 689 } | 694 } |
| 690 | 695 |
| 691 EVP_PKEY* key = NULL; | 696 EVP_PKEY* key = NULL; |
| 692 X509 *cert = NULL; | 697 X509 *cert = NULL; |
| 693 STACK_OF(X509) *ca_certs = NULL; | 698 STACK_OF(X509) *ca_certs = NULL; |
| 694 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); | 699 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
| 695 if (status == 0) { | 700 if (status == 0) { |
| 696 return status; | 701 return status; |
| 697 } | 702 } |
| 698 | 703 |
| 699 ScopedX509Stack cert_stack(ca_certs); | 704 ScopedX509Stack cert_stack(ca_certs); |
| 700 X509_STORE* store = SSL_CTX_get_cert_store(context); | 705 X509_STORE* store = SSL_CTX_get_cert_store(context); |
| 701 status = X509_STORE_add_cert(store, cert); | 706 status = X509_STORE_add_cert(store, cert); |
| 707 X509_free(cert); | |
| 702 if (status == 0) { | 708 if (status == 0) { |
| 703 X509_free(cert); | |
| 704 return status; | 709 return status; |
| 705 } | 710 } |
| 706 | 711 |
| 707 X509* ca; | 712 X509* ca; |
| 708 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { | 713 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
| 709 status = X509_STORE_add_cert(store, ca); | 714 status = X509_STORE_add_cert(store, ca); |
| 715 X509_free(ca); | |
| 710 if (status == 0) { | 716 if (status == 0) { |
| 711 X509_free(ca); | |
| 712 return status; | 717 return status; |
| 713 } | 718 } |
| 714 } | 719 } |
| 715 | 720 |
| 716 return status; | 721 return status; |
| 717 } | 722 } |
| 718 | 723 |
| 719 | 724 |
| 720 static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) { | 725 static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) { |
| 721 X509_STORE* store = SSL_CTX_get_cert_store(context); | 726 X509_STORE* store = SSL_CTX_get_cert_store(context); |
| 722 | 727 |
| 723 int status = 0; | 728 int status = 0; |
| 724 X509* cert = NULL; | 729 X509* cert = NULL; |
| 725 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { | 730 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 726 status = X509_STORE_add_cert(store, cert); | 731 status = X509_STORE_add_cert(store, cert); |
| 732 X509_free(cert); | |
| 727 if (status == 0) { | 733 if (status == 0) { |
| 728 X509_free(cert); | |
| 729 return status; | 734 return status; |
| 730 } | 735 } |
| 731 } | 736 } |
| 732 | 737 |
| 733 // If no PEM start line is found, it means that we read to the end of the | 738 // 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 | 739 // 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, | 740 // 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 | 741 // indicating that we should try to read as PKCS12. If there is some other |
| 737 // error, we return it up to the caller. | 742 // error, we return it up to the caller. |
| 738 return NoPEMStartLine() ? status : 0; | 743 return NoPEMStartLine() ? status : 0; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 752 } else { | 757 } else { |
| 753 // The PEM file was successfully parsed. | 758 // The PEM file was successfully parsed. |
| 754 ERR_clear_error(); | 759 ERR_clear_error(); |
| 755 } | 760 } |
| 756 return status; | 761 return status; |
| 757 } | 762 } |
| 758 | 763 |
| 759 | 764 |
| 760 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 765 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
| 761 Dart_NativeArguments args) { | 766 Dart_NativeArguments args) { |
| 762 SSL_CTX* context = GetSecurityContext(args); | 767 SSLContext* context = GetSecurityContext(args); |
| 763 const char* password = GetPasswordArgument(args, 2); | 768 const char* password = GetPasswordArgument(args, 2); |
| 764 int status; | 769 int status; |
| 765 { | 770 { |
| 766 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 771 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 767 status = SetTrustedCertificatesBytes(context, bio.bio(), password); | 772 status = SetTrustedCertificatesBytes( |
| 773 context->context(), bio.bio(), password); | |
| 768 } | 774 } |
| 769 CheckStatus(status, | 775 CheckStatus(status, |
| 770 "TlsException", | 776 "TlsException", |
| 771 "Failure in setTrustedCertificatesBytes"); | 777 "Failure in setTrustedCertificatesBytes"); |
| 772 } | 778 } |
| 773 | 779 |
| 774 | 780 |
| 775 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { | 781 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { |
| 776 Dart_SetReturnValue(args, Dart_NewBoolean(true)); | 782 Dart_SetReturnValue(args, Dart_NewBoolean(true)); |
| 777 } | 783 } |
| 778 | 784 |
| 779 | 785 |
| 780 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 786 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
| 781 Dart_NativeArguments args) { | 787 Dart_NativeArguments args) { |
| 782 SSL_CTX* context = GetSecurityContext(args); | 788 SSLContext* context = GetSecurityContext(args); |
| 783 #if defined(TARGET_OS_ANDROID) | 789 #if defined(TARGET_OS_ANDROID) |
| 784 // On Android, we don't compile in the trusted root certificates. Insead, | 790 // 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. | 791 // 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 | 792 // 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 | 793 // SSL_do_handshake will synchronously hit the filesystem looking for root |
| 788 // certs during its trust evaluation. We call SSL_do_handshake directly from | 794 // 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" | 795 // the Dart thread so that Dart code can be invoked from the "bad certificate" |
| 790 // callback called by SSL_do_handshake. | 796 // callback called by SSL_do_handshake. |
| 791 const char* android_cacerts = "/system/etc/security/cacerts"; | 797 const char* android_cacerts = "/system/etc/security/cacerts"; |
| 792 int status = SSL_CTX_load_verify_locations(context, NULL, android_cacerts); | 798 int status = SSL_CTX_load_verify_locations( |
| 799 context->context(), NULL, android_cacerts); | |
| 793 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); | 800 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); |
| 794 #else | 801 #else |
| 795 X509_STORE* store = SSL_CTX_get_cert_store(context); | 802 X509_STORE* store = SSL_CTX_get_cert_store(context->context()); |
| 796 BIO* roots_bio = | 803 BIO* roots_bio = |
| 797 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), | 804 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), |
| 798 root_certificates_pem_length); | 805 root_certificates_pem_length); |
| 799 X509* root_cert; | 806 X509* root_cert; |
| 800 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, | 807 // 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. | 808 // backed by a memory buffer), and returns X509 objects, one by one. |
| 802 // When the end of the bio is reached, it returns null. | 809 // 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) { | 810 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) { |
| 804 X509_STORE_add_cert(store, root_cert); | 811 int status = X509_STORE_add_cert(store, root_cert); |
| 812 X509_free(root_cert); | |
| 813 if (status == 0) { | |
| 814 break; | |
| 815 } | |
| 805 } | 816 } |
| 806 BIO_free(roots_bio); | 817 BIO_free(roots_bio); |
| 807 // If there is an error here, it must be the error indicating that we are done | 818 // If there is an error here, it must be the error indicating that we are done |
| 808 // reading PEM certificates. | 819 // reading PEM certificates. |
| 809 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); | 820 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); |
| 810 ERR_clear_error(); | 821 ERR_clear_error(); |
| 811 #endif // defined(TARGET_OS_ANDROID) | 822 #endif // defined(TARGET_OS_ANDROID) |
| 812 } | 823 } |
| 813 | 824 |
| 814 | 825 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 837 } | 848 } |
| 838 if (status == 0) { | 849 if (status == 0) { |
| 839 return status; | 850 return status; |
| 840 } | 851 } |
| 841 | 852 |
| 842 SSL_CTX_clear_chain_certs(context); | 853 SSL_CTX_clear_chain_certs(context); |
| 843 | 854 |
| 844 X509* ca; | 855 X509* ca; |
| 845 while ((ca = sk_X509_shift(certs.get())) != NULL) { | 856 while ((ca = sk_X509_shift(certs.get())) != NULL) { |
| 846 status = SSL_CTX_add0_chain_cert(context, ca); | 857 status = SSL_CTX_add0_chain_cert(context, ca); |
| 858 // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the | |
| 859 // call fails. | |
| 847 if (status == 0) { | 860 if (status == 0) { |
| 848 X509_free(ca); | 861 X509_free(ca); |
| 849 return status; | 862 return status; |
| 850 } | 863 } |
| 851 } | 864 } |
| 852 | 865 |
| 853 return status; | 866 return status; |
| 854 } | 867 } |
| 855 | 868 |
| 856 | 869 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 868 } | 881 } |
| 869 if (status == 0) { | 882 if (status == 0) { |
| 870 return status; | 883 return status; |
| 871 } | 884 } |
| 872 | 885 |
| 873 SSL_CTX_clear_chain_certs(context); | 886 SSL_CTX_clear_chain_certs(context); |
| 874 | 887 |
| 875 X509* ca; | 888 X509* ca; |
| 876 while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { | 889 while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 877 status = SSL_CTX_add0_chain_cert(context, ca); | 890 status = SSL_CTX_add0_chain_cert(context, ca); |
| 891 // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the | |
| 892 // call fails. | |
| 878 if (status == 0) { | 893 if (status == 0) { |
| 879 X509_free(ca); | 894 X509_free(ca); |
| 880 return status; | 895 return status; |
| 881 } | 896 } |
| 882 // Note that we must not free `ca` if it was successfully added to the | 897 // 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 | 898 // chain. We must free the main certificate x509, though since its reference |
| 884 // count is increased by SSL_CTX_use_certificate. | 899 // count is increased by SSL_CTX_use_certificate. |
| 885 } | 900 } |
| 886 | 901 |
| 887 return NoPEMStartLine() ? status : 0; | 902 return NoPEMStartLine() ? status : 0; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 899 } else { | 914 } else { |
| 900 // The PEM file was successfully read. | 915 // The PEM file was successfully read. |
| 901 ERR_clear_error(); | 916 ERR_clear_error(); |
| 902 } | 917 } |
| 903 return status; | 918 return status; |
| 904 } | 919 } |
| 905 | 920 |
| 906 | 921 |
| 907 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 922 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
| 908 Dart_NativeArguments args) { | 923 Dart_NativeArguments args) { |
| 909 SSL_CTX* context = GetSecurityContext(args); | 924 SSLContext* context = GetSecurityContext(args); |
| 910 const char* password = GetPasswordArgument(args, 2); | 925 const char* password = GetPasswordArgument(args, 2); |
| 911 int status; | 926 int status; |
| 912 { | 927 { |
| 913 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 928 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 914 status = UseChainBytes(context, bio.bio(), password); | 929 status = UseChainBytes(context->context(), bio.bio(), password); |
| 915 } | 930 } |
| 916 CheckStatus(status, | 931 CheckStatus(status, |
| 917 "TlsException", | 932 "TlsException", |
| 918 "Failure in useCertificateChainBytes"); | 933 "Failure in useCertificateChainBytes"); |
| 919 } | 934 } |
| 920 | 935 |
| 921 | 936 |
| 922 static int SetClientAuthoritiesPKCS12(SSL_CTX* context, | 937 static int SetClientAuthoritiesPKCS12(SSL_CTX* context, |
| 923 BIO* bio, | 938 BIO* bio, |
| 924 const char* password) { | 939 const char* password) { |
| 925 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 940 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
| 926 if (p12.get() == NULL) { | 941 if (p12.get() == NULL) { |
| 927 return 0; | 942 return 0; |
| 928 } | 943 } |
| 929 | 944 |
| 930 EVP_PKEY* key = NULL; | 945 EVP_PKEY* key = NULL; |
| 931 X509 *cert = NULL; | 946 X509 *cert = NULL; |
| 932 STACK_OF(X509) *ca_certs = NULL; | 947 STACK_OF(X509) *ca_certs = NULL; |
| 933 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); | 948 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
| 934 if (status == 0) { | 949 if (status == 0) { |
| 935 return status; | 950 return status; |
| 936 } | 951 } |
| 937 | 952 |
| 938 ScopedX509Stack cert_stack(ca_certs); | 953 ScopedX509Stack cert_stack(ca_certs); |
| 939 status = SSL_CTX_add_client_CA(context, cert); | 954 status = SSL_CTX_add_client_CA(context, cert); |
| 955 X509_free(cert); | |
|
siva
2016/08/04 17:25:03
Can you add a comment that SSL_CTX_add_client_CA i
zra
2016/08/04 17:49:34
Done.
| |
| 940 if (status == 0) { | 956 if (status == 0) { |
| 941 X509_free(cert); | |
| 942 return status; | 957 return status; |
| 943 } | 958 } |
| 944 | 959 |
| 945 X509* ca; | 960 X509* ca; |
| 946 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { | 961 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
| 947 status = SSL_CTX_add_client_CA(context, ca); | 962 status = SSL_CTX_add_client_CA(context, ca); |
| 948 X509_free(ca); // The name has been extracted. | 963 X509_free(ca); // The name has been extracted. |
| 949 if (status == 0) { | 964 if (status == 0) { |
| 950 return status; | 965 return status; |
| 951 } | 966 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 982 } else { | 997 } else { |
| 983 // The PEM file was successfully parsed. | 998 // The PEM file was successfully parsed. |
| 984 ERR_clear_error(); | 999 ERR_clear_error(); |
| 985 } | 1000 } |
| 986 return status; | 1001 return status; |
| 987 } | 1002 } |
| 988 | 1003 |
| 989 | 1004 |
| 990 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 1005 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
| 991 Dart_NativeArguments args) { | 1006 Dart_NativeArguments args) { |
| 992 SSL_CTX* context = GetSecurityContext(args); | 1007 SSLContext* context = GetSecurityContext(args); |
| 993 const char* password = GetPasswordArgument(args, 2); | 1008 const char* password = GetPasswordArgument(args, 2); |
| 994 | 1009 |
| 995 int status; | 1010 int status; |
| 996 { | 1011 { |
| 997 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 1012 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 998 status = SetClientAuthorities(context, bio.bio(), password); | 1013 status = SetClientAuthorities(context->context(), bio.bio(), password); |
| 999 } | 1014 } |
| 1000 | 1015 |
| 1001 CheckStatus(status, | 1016 CheckStatus(status, |
| 1002 "TlsException", | 1017 "TlsException", |
| 1003 "Failure in setClientAuthoritiesBytes"); | 1018 "Failure in setClientAuthoritiesBytes"); |
| 1004 } | 1019 } |
| 1005 | 1020 |
| 1006 | 1021 |
| 1007 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( | 1022 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( |
| 1008 Dart_NativeArguments args) { | 1023 Dart_NativeArguments args) { |
| 1009 SSL_CTX* context = GetSecurityContext(args); | 1024 SSLContext* context = GetSecurityContext(args); |
| 1010 Dart_Handle protocols_handle = | 1025 Dart_Handle protocols_handle = |
| 1011 ThrowIfError(Dart_GetNativeArgument(args, 1)); | 1026 ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| 1012 Dart_Handle is_server_handle = | 1027 Dart_Handle is_server_handle = |
| 1013 ThrowIfError(Dart_GetNativeArgument(args, 2)); | 1028 ThrowIfError(Dart_GetNativeArgument(args, 2)); |
| 1014 if (Dart_IsBoolean(is_server_handle)) { | 1029 if (Dart_IsBoolean(is_server_handle)) { |
| 1015 bool is_server = DartUtils::GetBooleanValue(is_server_handle); | 1030 bool is_server = DartUtils::GetBooleanValue(is_server_handle); |
| 1016 SetAlpnProtocolList(protocols_handle, NULL, context, is_server); | 1031 SetAlpnProtocolList(protocols_handle, NULL, context, is_server); |
| 1017 } else { | 1032 } else { |
| 1018 Dart_ThrowException(DartUtils::NewDartArgumentError( | 1033 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 1019 "Non-boolean is_server argument passed to SetAlpnProtocols")); | 1034 "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; | 1371 server_list += protocol_length; |
| 1357 } | 1372 } |
| 1358 // TODO(23580): Make failure send a fatal alert instead of ignoring ALPN. | 1373 // TODO(23580): Make failure send a fatal alert instead of ignoring ALPN. |
| 1359 return SSL_TLSEXT_ERR_NOACK; | 1374 return SSL_TLSEXT_ERR_NOACK; |
| 1360 } | 1375 } |
| 1361 | 1376 |
| 1362 | 1377 |
| 1363 // Sets the protocol list for ALPN on a SSL object or a context. | 1378 // Sets the protocol list for ALPN on a SSL object or a context. |
| 1364 static void SetAlpnProtocolList(Dart_Handle protocols_handle, | 1379 static void SetAlpnProtocolList(Dart_Handle protocols_handle, |
| 1365 SSL* ssl, | 1380 SSL* ssl, |
| 1366 SSL_CTX* context, | 1381 SSLContext* context, |
| 1367 bool is_server) { | 1382 bool is_server) { |
| 1368 // Enable ALPN (application layer protocol negotiation) if the caller provides | 1383 // Enable ALPN (application layer protocol negotiation) if the caller provides |
| 1369 // a valid list of supported protocols. | 1384 // a valid list of supported protocols. |
| 1370 Dart_TypedData_Type protocols_type; | 1385 Dart_TypedData_Type protocols_type; |
| 1371 uint8_t* protocol_string = NULL; | 1386 uint8_t* protocol_string = NULL; |
| 1372 uint8_t* protocol_string_copy = NULL; | 1387 uint8_t* protocol_string_copy = NULL; |
| 1373 intptr_t protocol_string_len = 0; | 1388 intptr_t protocol_string_len = 0; |
| 1374 int status; | 1389 int status; |
| 1375 | 1390 |
| 1376 Dart_Handle result = Dart_TypedDataAcquireData( | 1391 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, | 1408 // ALPN on server connections must be set on an SSL_CTX object, |
| 1394 // not on the SSL object of the individual connection. | 1409 // not on the SSL object of the individual connection. |
| 1395 ASSERT(context != NULL); | 1410 ASSERT(context != NULL); |
| 1396 ASSERT(ssl == NULL); | 1411 ASSERT(ssl == NULL); |
| 1397 // Because it must be passed as a single void*, terminate | 1412 // Because it must be passed as a single void*, terminate |
| 1398 // the list of (length, data) strings with a length 0 string. | 1413 // the list of (length, data) strings with a length 0 string. |
| 1399 protocol_string_copy = | 1414 protocol_string_copy = |
| 1400 static_cast<uint8_t*>(malloc(protocol_string_len + 1)); | 1415 static_cast<uint8_t*>(malloc(protocol_string_len + 1)); |
| 1401 memmove(protocol_string_copy, protocol_string, protocol_string_len); | 1416 memmove(protocol_string_copy, protocol_string, protocol_string_len); |
| 1402 protocol_string_copy[protocol_string_len] = '\0'; | 1417 protocol_string_copy[protocol_string_len] = '\0'; |
| 1403 SSL_CTX_set_alpn_select_cb(context, AlpnCallback, protocol_string_copy); | 1418 SSL_CTX_set_alpn_select_cb( |
| 1404 // TODO(whesse): If this function is called again, free the previous | 1419 context->context(), AlpnCallback, protocol_string_copy); |
| 1405 // protocol_string_copy. It may be better to keep this as a native | 1420 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 { | 1421 } else { |
| 1411 // The function makes a local copy of protocol_string, which it owns. | 1422 // The function makes a local copy of protocol_string, which it owns. |
| 1412 if (ssl != NULL) { | 1423 if (ssl != NULL) { |
| 1413 ASSERT(context == NULL); | 1424 ASSERT(context == NULL); |
| 1414 status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len); | 1425 status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len); |
| 1415 } else { | 1426 } else { |
| 1416 ASSERT(context != NULL); | 1427 ASSERT(context != NULL); |
| 1417 ASSERT(ssl == NULL); | 1428 ASSERT(ssl == NULL); |
| 1418 status = SSL_CTX_set_alpn_protos( | 1429 status = SSL_CTX_set_alpn_protos( |
| 1419 context, protocol_string, protocol_string_len); | 1430 context->context(), protocol_string, protocol_string_len); |
| 1420 } | 1431 } |
| 1421 ASSERT(status == 0); // The function returns a non-standard status. | 1432 ASSERT(status == 0); // The function returns a non-standard status. |
| 1422 } | 1433 } |
| 1423 } | 1434 } |
| 1424 Dart_TypedDataReleaseData(protocols_handle); | 1435 Dart_TypedDataReleaseData(protocols_handle); |
| 1425 } | 1436 } |
| 1426 | 1437 |
| 1427 | 1438 |
| 1428 void SSLFilter::Connect(const char* hostname, | 1439 void SSLFilter::Connect(const char* hostname, |
| 1429 SSL_CTX* context, | 1440 SSL_CTX* context, |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1688 return bytes_processed; | 1699 return bytes_processed; |
| 1689 } | 1700 } |
| 1690 | 1701 |
| 1691 } // namespace bin | 1702 } // namespace bin |
| 1692 } // namespace dart | 1703 } // namespace dart |
| 1693 | 1704 |
| 1694 #endif // defined(TARGET_OS_LINUX) | 1705 #endif // defined(TARGET_OS_LINUX) |
| 1695 | 1706 |
| 1696 #endif // !defined(DART_IO_DISABLED) && | 1707 #endif // !defined(DART_IO_DISABLED) && |
| 1697 // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1708 // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
| OLD | NEW |