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 10 matching lines...) Expand all Loading... | |
21 #include <openssl/bio.h> | 21 #include <openssl/bio.h> |
22 #include <openssl/err.h> | 22 #include <openssl/err.h> |
23 #include <openssl/pkcs12.h> | 23 #include <openssl/pkcs12.h> |
24 #include <openssl/safestack.h> | 24 #include <openssl/safestack.h> |
25 #include <openssl/ssl.h> | 25 #include <openssl/ssl.h> |
26 #include <openssl/tls1.h> | 26 #include <openssl/tls1.h> |
27 #include <openssl/x509.h> | 27 #include <openssl/x509.h> |
28 | 28 |
29 #include "bin/builtin.h" | 29 #include "bin/builtin.h" |
30 #include "bin/dartutils.h" | 30 #include "bin/dartutils.h" |
31 #include "bin/directory.h" | |
32 #include "bin/file.h" | |
31 #include "bin/lockers.h" | 33 #include "bin/lockers.h" |
32 #include "bin/log.h" | 34 #include "bin/log.h" |
33 #include "bin/socket.h" | 35 #include "bin/socket.h" |
34 #include "bin/thread.h" | 36 #include "bin/thread.h" |
35 #include "bin/utils.h" | 37 #include "bin/utils.h" |
36 #include "platform/utils.h" | 38 #include "platform/utils.h" |
37 | 39 |
38 #include "include/dart_api.h" | 40 #include "include/dart_api.h" |
39 | 41 |
40 // Return the error from the containing function if handle is an error handle. | 42 // Return the error from the containing function if handle is an error handle. |
(...skipping 16 matching lines...) Expand all Loading... | |
57 static const int kSSLFilterNativeFieldIndex = 0; | 59 static const int kSSLFilterNativeFieldIndex = 0; |
58 static const int kSecurityContextNativeFieldIndex = 0; | 60 static const int kSecurityContextNativeFieldIndex = 0; |
59 static const int kX509NativeFieldIndex = 0; | 61 static const int kX509NativeFieldIndex = 0; |
60 | 62 |
61 static const bool SSL_LOG_STATUS = false; | 63 static const bool SSL_LOG_STATUS = false; |
62 static const bool SSL_LOG_DATA = false; | 64 static const bool SSL_LOG_DATA = false; |
63 | 65 |
64 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; | 66 static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000; |
65 | 67 |
66 | 68 |
69 const char* commandline_root_certs_file = NULL; | |
70 const char* commandline_root_certs_cache = NULL; | |
71 | |
72 | |
67 /* Get the error messages from BoringSSL, and put them in buffer as a | 73 /* Get the error messages from BoringSSL, and put them in buffer as a |
68 * null-terminated string. */ | 74 * null-terminated string. */ |
69 static void FetchErrorString(char* buffer, int length) { | 75 static void FetchErrorString(char* buffer, int length) { |
70 buffer[0] = '\0'; | 76 buffer[0] = '\0'; |
71 int error = ERR_get_error(); | 77 int error = ERR_get_error(); |
72 while (error != 0) { | 78 while (error != 0) { |
73 int used = strlen(buffer); | 79 int used = strlen(buffer); |
74 int free_length = length - used; | 80 int free_length = length - used; |
75 if (free_length > 16) { | 81 if (free_length > 16) { |
76 // Enough room for error code at least. | 82 // Enough room for error code at least. |
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 "TlsException", | 787 "TlsException", |
782 "Failure in setTrustedCertificatesBytes"); | 788 "Failure in setTrustedCertificatesBytes"); |
783 } | 789 } |
784 | 790 |
785 | 791 |
786 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { | 792 void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { |
787 Dart_SetReturnValue(args, Dart_NewBoolean(true)); | 793 Dart_SetReturnValue(args, Dart_NewBoolean(true)); |
788 } | 794 } |
789 | 795 |
790 | 796 |
791 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 797 static void AddCompiledInCerts(SSLContext* context) { |
792 Dart_NativeArguments args) { | 798 if (root_certificates_pem == NULL) { |
793 SSLContext* context = GetSecurityContext(args); | 799 return; |
794 #if defined(TARGET_OS_ANDROID) | 800 } |
795 // On Android, we don't compile in the trusted root certificates. Insead, | |
796 // we use the directory of trusted certificates already present on the device. | |
797 // This saves ~240KB from the size of the binary. This has the drawback that | |
798 // SSL_do_handshake will synchronously hit the filesystem looking for root | |
799 // certs during its trust evaluation. We call SSL_do_handshake directly from | |
800 // the Dart thread so that Dart code can be invoked from the "bad certificate" | |
801 // callback called by SSL_do_handshake. | |
802 const char* android_cacerts = "/system/etc/security/cacerts"; | |
803 int status = SSL_CTX_load_verify_locations( | |
804 context->context(), NULL, android_cacerts); | |
805 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); | |
806 #else | |
807 X509_STORE* store = SSL_CTX_get_cert_store(context->context()); | 801 X509_STORE* store = SSL_CTX_get_cert_store(context->context()); |
808 BIO* roots_bio = | 802 BIO* roots_bio = |
809 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), | 803 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), |
810 root_certificates_pem_length); | 804 root_certificates_pem_length); |
811 X509* root_cert; | 805 X509* root_cert; |
812 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, | 806 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, |
813 // backed by a memory buffer), and returns X509 objects, one by one. | 807 // backed by a memory buffer), and returns X509 objects, one by one. |
814 // When the end of the bio is reached, it returns null. | 808 // When the end of the bio is reached, it returns null. |
815 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) { | 809 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) { |
816 int status = X509_STORE_add_cert(store, root_cert); | 810 int status = X509_STORE_add_cert(store, root_cert); |
817 // X509_STORE_add_cert increments the reference count of cert on success. | 811 // X509_STORE_add_cert increments the reference count of cert on success. |
818 X509_free(root_cert); | 812 X509_free(root_cert); |
819 if (status == 0) { | 813 if (status == 0) { |
820 break; | 814 break; |
821 } | 815 } |
822 } | 816 } |
823 BIO_free(roots_bio); | 817 BIO_free(roots_bio); |
824 // 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 |
825 // reading PEM certificates. | 819 // reading PEM certificates. |
826 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); | 820 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); |
827 ERR_clear_error(); | 821 ERR_clear_error(); |
828 #endif // defined(TARGET_OS_ANDROID) | |
829 } | 822 } |
830 | 823 |
831 | 824 |
825 static void LoadRootCertFile(SSLContext* context, const char* file) { | |
826 if (SSL_LOG_STATUS) { | |
827 Log::Print("Looking for trusted roots in %s\n", file); | |
828 } | |
829 if (!File::Exists(file)) { | |
830 ThrowIOException(-1, "TlsException", "Failed to find root cert file"); | |
831 } | |
832 int status = SSL_CTX_load_verify_locations(context->context(), file, NULL); | |
833 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); | |
834 if (SSL_LOG_STATUS) { | |
835 Log::Print("Trusting roots from: %s\n", file); | |
836 } | |
837 } | |
838 | |
839 | |
840 static void LoadRootCertCache(SSLContext* context, const char* cache) { | |
841 if (SSL_LOG_STATUS) { | |
842 Log::Print("Looking for trusted roots in %s\n", cache); | |
843 } | |
844 if (Directory::Exists(cache) != Directory::EXISTS) { | |
845 ThrowIOException(-1, "TlsException", "Failed to find root cert cache"); | |
846 } | |
847 int status = SSL_CTX_load_verify_locations(context->context(), NULL, cache); | |
848 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); | |
849 if (SSL_LOG_STATUS) { | |
850 Log::Print("Trusting roots from: %s\n", cache); | |
851 } | |
852 } | |
siva
2016/09/16 01:27:12
These functions are not used under TARGET_OS_MACOS
zra
2016/09/16 16:08:02
On Mac and iOS we use the SecureTransport API from
| |
853 | |
854 | |
855 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | |
856 Dart_NativeArguments args) { | |
857 SSLContext* context = GetSecurityContext(args); | |
858 | |
859 // First, try to use locations specified on the command line. | |
860 if (commandline_root_certs_file != NULL) { | |
861 LoadRootCertFile(context, commandline_root_certs_file); | |
862 return; | |
863 } | |
864 | |
865 if (commandline_root_certs_cache != NULL) { | |
866 LoadRootCertCache(context, commandline_root_certs_cache); | |
867 return; | |
868 } | |
siva
2016/09/16 01:27:12
These command lines are not supported under TARGET
zra
2016/09/16 16:08:02
Ditto
| |
869 | |
870 #if defined(TARGET_OS_ANDROID) | |
871 // On Android, we don't compile in the trusted root certificates. Insead, | |
872 // we use the directory of trusted certificates already present on the device. | |
873 // This saves ~240KB from the size of the binary. This has the drawback that | |
874 // SSL_do_handshake will synchronously hit the filesystem looking for root | |
875 // certs during its trust evaluation. We call SSL_do_handshake directly from | |
876 // the Dart thread so that Dart code can be invoked from the "bad certificate" | |
877 // callback called by SSL_do_handshake. | |
878 const char* android_cacerts = "/system/etc/security/cacerts"; | |
879 LoadRootCertCache(context, android_cacerts); | |
880 return; | |
881 #elif defined(TARGET_OS_LINUX) | |
882 // On Linux, we use the compiled-in trusted certs as a last resort. First, | |
883 // we try to find the trusted certs in various standard locations. A good | |
884 // discussion of the complexities of this endeavor can be found here: | |
885 // | |
886 // https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certif icate-stores-and-platforms/ | |
887 const char* bundle = "/etc/pki/tls/certs/ca-bundle.crt"; | |
888 const char* cachedir = "/etc/ssl/certs"; | |
889 if (File::Exists(bundle)) { | |
890 LoadRootCertFile(context, bundle); | |
891 return; | |
892 } | |
893 | |
894 if (Directory::Exists(cachedir) == Directory::EXISTS) { | |
895 LoadRootCertCache(context, cachedir); | |
896 return; | |
897 } | |
898 #endif // defined(TARGET_OS_ANDROID) | |
899 | |
900 // Fall back on the compiled-in certs if the standard locations don't exist, | |
901 // or we aren't on Linux. | |
902 AddCompiledInCerts(context); | |
903 if (SSL_LOG_STATUS) { | |
904 Log::Print("Trusting compiled-in roots\n"); | |
905 } | |
906 } | |
907 | |
908 | |
832 static int UseChainBytesPKCS12(SSL_CTX* context, | 909 static int UseChainBytesPKCS12(SSL_CTX* context, |
833 BIO* bio, | 910 BIO* bio, |
834 const char* password) { | 911 const char* password) { |
835 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 912 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
836 if (p12.get() == NULL) { | 913 if (p12.get() == NULL) { |
837 return 0; | 914 return 0; |
838 } | 915 } |
839 | 916 |
840 EVP_PKEY* key = NULL; | 917 EVP_PKEY* key = NULL; |
841 X509 *cert = NULL; | 918 X509 *cert = NULL; |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1487 X509_V_FLAG_TRUSTED_FIRST); | 1564 X509_V_FLAG_TRUSTED_FIRST); |
1488 X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0); | 1565 X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0); |
1489 status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters, | 1566 status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters, |
1490 hostname_, strlen(hostname_)); | 1567 hostname_, strlen(hostname_)); |
1491 CheckStatus(status, "TlsException", | 1568 CheckStatus(status, "TlsException", |
1492 "Set hostname for certificate checking"); | 1569 "Set hostname for certificate checking"); |
1493 } | 1570 } |
1494 // Make the connection: | 1571 // Make the connection: |
1495 if (is_server_) { | 1572 if (is_server_) { |
1496 status = SSL_accept(ssl_); | 1573 status = SSL_accept(ssl_); |
1497 if (SSL_LOG_STATUS) Log::Print("SSL_accept status: %d\n", status); | 1574 if (SSL_LOG_STATUS) { |
1575 Log::Print("SSL_accept status: %d\n", status); | |
1576 } | |
1498 if (status != 1) { | 1577 if (status != 1) { |
1499 // TODO(whesse): expect a needs-data error here. Handle other errors. | 1578 // TODO(whesse): expect a needs-data error here. Handle other errors. |
1500 error = SSL_get_error(ssl_, status); | 1579 error = SSL_get_error(ssl_, status); |
1501 if (SSL_LOG_STATUS) Log::Print("SSL_accept error: %d\n", error); | 1580 if (SSL_LOG_STATUS) { |
1581 Log::Print("SSL_accept error: %d\n", error); | |
1582 } | |
1502 } | 1583 } |
1503 } else { | 1584 } else { |
1504 status = SSL_connect(ssl_); | 1585 status = SSL_connect(ssl_); |
1505 if (SSL_LOG_STATUS) Log::Print("SSL_connect status: %d\n", status); | 1586 if (SSL_LOG_STATUS) { |
1587 Log::Print("SSL_connect status: %d\n", status); | |
1588 } | |
1506 if (status != 1) { | 1589 if (status != 1) { |
1507 // TODO(whesse): expect a needs-data error here. Handle other errors. | 1590 // TODO(whesse): expect a needs-data error here. Handle other errors. |
1508 error = SSL_get_error(ssl_, status); | 1591 error = SSL_get_error(ssl_, status); |
1509 if (SSL_LOG_STATUS) Log::Print("SSL_connect error: %d\n", error); | 1592 if (SSL_LOG_STATUS) { |
1593 Log::Print("SSL_connect error: %d\n", error); | |
1594 } | |
1510 } | 1595 } |
1511 } | 1596 } |
1512 Handshake(); | 1597 Handshake(); |
1513 } | 1598 } |
1514 | 1599 |
1515 | 1600 |
1516 int printErrorCallback(const char *str, size_t len, void *ctx) { | 1601 int printErrorCallback(const char *str, size_t len, void *ctx) { |
1517 Log::PrintErr("%.*s\n", static_cast<int>(len), str); | 1602 Log::PrintErr("%.*s\n", static_cast<int>(len), str); |
1518 return 1; | 1603 return 1; |
1519 } | 1604 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1707 return bytes_processed; | 1792 return bytes_processed; |
1708 } | 1793 } |
1709 | 1794 |
1710 } // namespace bin | 1795 } // namespace bin |
1711 } // namespace dart | 1796 } // namespace dart |
1712 | 1797 |
1713 #endif // defined(TARGET_OS_LINUX) | 1798 #endif // defined(TARGET_OS_LINUX) |
1714 | 1799 |
1715 #endif // !defined(DART_IO_DISABLED) && | 1800 #endif // !defined(DART_IO_DISABLED) && |
1716 // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1801 // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
OLD | NEW |