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 } |
| 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 } |
| 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 |