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 |