Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Side by Side Diff: runtime/bin/secure_socket_boringssl.cc

Issue 2346683003: Use OS-provided trusted root certs on Linux (Closed)
Patch Set: Address comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/bin/root_certificates_unsupported.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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)
OLDNEW
« no previous file with comments | « runtime/bin/root_certificates_unsupported.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698