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) { |
P.Y.L.
2016/09/15 18:41:48
Now that compiled-in certs are a fallback, you mig
zra
2016/09/15 19:18:22
I've changed root_certificates_unsupported.cc so t
| |
792 Dart_NativeArguments args) { | |
793 SSLContext* context = GetSecurityContext(args); | |
794 #if defined(TARGET_OS_ANDROID) | |
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()); | 798 X509_STORE* store = SSL_CTX_get_cert_store(context->context()); |
808 BIO* roots_bio = | 799 BIO* roots_bio = |
809 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), | 800 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), |
810 root_certificates_pem_length); | 801 root_certificates_pem_length); |
811 X509* root_cert; | 802 X509* root_cert; |
812 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, | 803 // 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. | 804 // backed by a memory buffer), and returns X509 objects, one by one. |
814 // When the end of the bio is reached, it returns null. | 805 // 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) { | 806 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) { |
816 int status = X509_STORE_add_cert(store, root_cert); | 807 int status = X509_STORE_add_cert(store, root_cert); |
817 // X509_STORE_add_cert increments the reference count of cert on success. | 808 // X509_STORE_add_cert increments the reference count of cert on success. |
818 X509_free(root_cert); | 809 X509_free(root_cert); |
819 if (status == 0) { | 810 if (status == 0) { |
820 break; | 811 break; |
821 } | 812 } |
822 } | 813 } |
823 BIO_free(roots_bio); | 814 BIO_free(roots_bio); |
824 // If there is an error here, it must be the error indicating that we are done | 815 // If there is an error here, it must be the error indicating that we are done |
825 // reading PEM certificates. | 816 // reading PEM certificates. |
826 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); | 817 ASSERT((ERR_peek_error() == 0) || NoPEMStartLine()); |
827 ERR_clear_error(); | 818 ERR_clear_error(); |
828 #endif // defined(TARGET_OS_ANDROID) | |
829 } | 819 } |
830 | 820 |
831 | 821 |
822 static void LoadRootCertFile(SSLContext* context, const char* file) { | |
823 if (SSL_LOG_STATUS) { | |
824 Log::Print("Looking for trusted roots in %s\n", file); | |
825 } | |
826 if (!File::Exists(file)) { | |
827 ThrowIOException(-1, "TlsException", "Failed to find root cert file"); | |
828 } | |
829 int status = SSL_CTX_load_verify_locations(context->context(), file, NULL); | |
830 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); | |
831 if (SSL_LOG_STATUS) { | |
832 Log::Print("Trusting roots from: %s\n", file); | |
833 } | |
834 } | |
835 | |
836 | |
837 static void LoadRootCertCache(SSLContext* context, const char* cache) { | |
838 if (SSL_LOG_STATUS) { | |
839 Log::Print("Looking for trusted roots in %s\n", cache); | |
840 } | |
841 if (Directory::Exists(cache) != Directory::EXISTS) { | |
842 ThrowIOException(-1, "TlsException", "Failed to find root cert cache"); | |
843 } | |
844 int status = SSL_CTX_load_verify_locations(context->context(), NULL, cache); | |
845 CheckStatus(status, "TlsException", "Failure trusting builtint roots"); | |
846 if (SSL_LOG_STATUS) { | |
847 Log::Print("Trusting roots from: %s\n", cache); | |
848 } | |
849 } | |
850 | |
851 | |
852 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | |
853 Dart_NativeArguments args) { | |
854 SSLContext* context = GetSecurityContext(args); | |
855 | |
856 // First, ry to use locations specified on the command line. | |
P.Y.L.
2016/09/15 18:24:05
try*
zra
2016/09/15 19:18:22
Done.
| |
857 if (commandline_root_certs_file != NULL) { | |
858 LoadRootCertFile(context, commandline_root_certs_file); | |
859 return; | |
860 } | |
861 | |
862 if (commandline_root_certs_cache != NULL) { | |
863 LoadRootCertCache(context, commandline_root_certs_cache); | |
864 return; | |
865 } | |
866 | |
867 #if defined(TARGET_OS_ANDROID) | |
868 // On Android, we don't compile in the trusted root certificates. Insead, | |
869 // we use the directory of trusted certificates already present on the device. | |
870 // This saves ~240KB from the size of the binary. This has the drawback that | |
871 // SSL_do_handshake will synchronously hit the filesystem looking for root | |
872 // certs during its trust evaluation. We call SSL_do_handshake directly from | |
873 // the Dart thread so that Dart code can be invoked from the "bad certificate" | |
874 // callback called by SSL_do_handshake. | |
875 const char* android_cacerts = "/system/etc/security/cacerts"; | |
876 LoadRootCertCache(context, android_cacerts); | |
877 return; | |
878 #elif defined(TARGET_OS_LINUX) | |
879 // On Linux, we use the compiled-in trusted certs as a last resort. First, | |
880 // we try to find the trusted certs in various standard locations. A good | |
881 // discussion of the complexities of this endeavor can be found here: | |
882 // | |
883 // https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certif icate-stores-and-platforms/ | |
884 const char* bundle = "/etc/pki/tls/certs/ca-bundle.crt"; | |
885 const char* cachedir = "/etc/ssl/certs"; | |
886 if (File::Exists(bundle)) { | |
887 LoadRootCertFile(context, bundle); | |
888 return; | |
889 } | |
890 | |
891 if (Directory::Exists(cachedir) == Directory::EXISTS) { | |
892 LoadRootCertCache(context, cachedir); | |
893 return; | |
894 } | |
895 #endif // defined(TARGET_OS_ANDROID) | |
896 | |
897 // Fall back on the compiled-in certs if the standard locations don't exist, | |
898 // or we aren't on Linux. | |
899 AddCompiledInCerts(context); | |
900 if (SSL_LOG_STATUS) { | |
901 Log::Print("Trusting compiled-in roots\n"); | |
902 } | |
903 } | |
904 | |
905 | |
832 static int UseChainBytesPKCS12(SSL_CTX* context, | 906 static int UseChainBytesPKCS12(SSL_CTX* context, |
833 BIO* bio, | 907 BIO* bio, |
834 const char* password) { | 908 const char* password) { |
835 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 909 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
836 if (p12.get() == NULL) { | 910 if (p12.get() == NULL) { |
837 return 0; | 911 return 0; |
838 } | 912 } |
839 | 913 |
840 EVP_PKEY* key = NULL; | 914 EVP_PKEY* key = NULL; |
841 X509 *cert = NULL; | 915 X509 *cert = NULL; |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1487 X509_V_FLAG_TRUSTED_FIRST); | 1561 X509_V_FLAG_TRUSTED_FIRST); |
1488 X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0); | 1562 X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0); |
1489 status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters, | 1563 status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters, |
1490 hostname_, strlen(hostname_)); | 1564 hostname_, strlen(hostname_)); |
1491 CheckStatus(status, "TlsException", | 1565 CheckStatus(status, "TlsException", |
1492 "Set hostname for certificate checking"); | 1566 "Set hostname for certificate checking"); |
1493 } | 1567 } |
1494 // Make the connection: | 1568 // Make the connection: |
1495 if (is_server_) { | 1569 if (is_server_) { |
1496 status = SSL_accept(ssl_); | 1570 status = SSL_accept(ssl_); |
1497 if (SSL_LOG_STATUS) Log::Print("SSL_accept status: %d\n", status); | 1571 if (SSL_LOG_STATUS) { |
1572 Log::Print("SSL_accept status: %d\n", status); | |
1573 } | |
1498 if (status != 1) { | 1574 if (status != 1) { |
1499 // TODO(whesse): expect a needs-data error here. Handle other errors. | 1575 // TODO(whesse): expect a needs-data error here. Handle other errors. |
1500 error = SSL_get_error(ssl_, status); | 1576 error = SSL_get_error(ssl_, status); |
1501 if (SSL_LOG_STATUS) Log::Print("SSL_accept error: %d\n", error); | 1577 if (SSL_LOG_STATUS) { |
1578 Log::Print("SSL_accept error: %d\n", error); | |
1579 } | |
1502 } | 1580 } |
1503 } else { | 1581 } else { |
1504 status = SSL_connect(ssl_); | 1582 status = SSL_connect(ssl_); |
1505 if (SSL_LOG_STATUS) Log::Print("SSL_connect status: %d\n", status); | 1583 if (SSL_LOG_STATUS) { |
1584 Log::Print("SSL_connect status: %d\n", status); | |
1585 } | |
1506 if (status != 1) { | 1586 if (status != 1) { |
1507 // TODO(whesse): expect a needs-data error here. Handle other errors. | 1587 // TODO(whesse): expect a needs-data error here. Handle other errors. |
1508 error = SSL_get_error(ssl_, status); | 1588 error = SSL_get_error(ssl_, status); |
1509 if (SSL_LOG_STATUS) Log::Print("SSL_connect error: %d\n", error); | 1589 if (SSL_LOG_STATUS) { |
1590 Log::Print("SSL_connect error: %d\n", error); | |
1591 } | |
1510 } | 1592 } |
1511 } | 1593 } |
1512 Handshake(); | 1594 Handshake(); |
1513 } | 1595 } |
1514 | 1596 |
1515 | 1597 |
1516 int printErrorCallback(const char *str, size_t len, void *ctx) { | 1598 int printErrorCallback(const char *str, size_t len, void *ctx) { |
1517 Log::PrintErr("%.*s\n", static_cast<int>(len), str); | 1599 Log::PrintErr("%.*s\n", static_cast<int>(len), str); |
1518 return 1; | 1600 return 1; |
1519 } | 1601 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1707 return bytes_processed; | 1789 return bytes_processed; |
1708 } | 1790 } |
1709 | 1791 |
1710 } // namespace bin | 1792 } // namespace bin |
1711 } // namespace dart | 1793 } // namespace dart |
1712 | 1794 |
1713 #endif // defined(TARGET_OS_LINUX) | 1795 #endif // defined(TARGET_OS_LINUX) |
1714 | 1796 |
1715 #endif // !defined(DART_IO_DISABLED) && | 1797 #endif // !defined(DART_IO_DISABLED) && |
1716 // !defined(DART_IO_SECURE_SOCKET_DISABLED) | 1798 // !defined(DART_IO_SECURE_SOCKET_DISABLED) |
OLD | NEW |