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