LCOV - code coverage report
Current view: top level - waltz/openssl - fd_openssl_tile.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 91 0.0 %
Date: 2025-12-07 04:58:33 Functions: 0 5 0.0 %

          Line data    Source code
       1             : #if FD_HAS_OPENSSL
       2             : #include "../../util/bits/fd_bits.h"
       3             : #include "fd_openssl_tile.h"
       4             : 
       5             : #include <dirent.h>
       6             : #include <unistd.h>
       7             : #include <errno.h>
       8             : 
       9             : /* Thread-local alloc object for each tile that uses OpenSSL. */
      10             : FD_TL fd_alloc_t * fd_ossl_alloc        = NULL;
      11             : FD_TL ulong        fd_ossl_alloc_errors = 0UL;
      12             : 
      13             : /* OpenSSL tries to read files and allocate memory and other dumb things
      14             :    on a thread local basis, so we need a special initializer process to
      15             :    make OpenSSL use our custom allocators before seccomp kicks in.
      16             : 
      17             :    OpenSSL allows us to specify custom memory allocation functions,
      18             :    which we want to point to an fd_alloc_t, but it does not let us use a
      19             :    context object.  Instead we stash it in this thread local, which is
      20             :    OK because the parent workspace exists for the duration of the SSL
      21             :    context, and the process only has one thread.
      22             : 
      23             :    Currently fd_alloc doesn't support realloc, so it's implemented on
      24             :    top of malloc and free, and then also it doesn't support getting the
      25             :    size of an allocation from the pointer, which we need for realloc, so
      26             :    we pad each alloc by 8 bytes and stuff the size into the first 8
      27             :    bytes. */
      28             : 
      29             : static void *
      30             : crypto_malloc( ulong        num,
      31             :                char const * file,
      32           0 :                int          line ) {
      33           0 :   (void)file;
      34           0 :   (void)line;
      35           0 :   void * result = fd_alloc_malloc( fd_ossl_alloc, 8UL, num + 8UL );
      36           0 :   if( FD_UNLIKELY( !result ) ) {
      37           0 :     fd_ossl_alloc_errors++;
      38           0 :     return NULL;
      39           0 :   }
      40           0 :   *(ulong*)result = num;
      41           0 :   return (uchar*)result + 8UL;
      42           0 : }
      43             : 
      44             : static void
      45             : crypto_free( void *       addr,
      46             :              char const * file,
      47           0 :              int          line ) {
      48           0 :   (void)file;
      49           0 :   (void)line;
      50             : 
      51           0 :   if( FD_UNLIKELY( !addr ) ) return;
      52           0 :   fd_alloc_free( fd_ossl_alloc, (uchar*)addr - 8UL );
      53           0 : }
      54             : 
      55             : static void *
      56             : crypto_realloc( void *       addr,
      57             :                 ulong        num,
      58             :                 char const * file,
      59           0 :                 int          line ) {
      60           0 :   (void)file;
      61           0 :   (void)line;
      62             : 
      63           0 :   if( FD_UNLIKELY( !addr ) ) return crypto_malloc( num, file, line );
      64           0 :   if( FD_UNLIKELY( !num ) ) {
      65           0 :     crypto_free( addr, file, line );
      66           0 :     return NULL;
      67           0 :   }
      68             : 
      69           0 :   void * new = fd_alloc_malloc( fd_ossl_alloc, 8UL, num + 8UL );
      70           0 :   if( FD_UNLIKELY( !new ) ) return NULL;
      71             : 
      72           0 :   ulong old_num = *(ulong*)( (uchar*)addr - 8UL );
      73           0 :   fd_memcpy( (uchar*)new + 8, (uchar*)addr, fd_ulong_min( old_num, num ) );
      74           0 :   fd_alloc_free( fd_ossl_alloc, (uchar*)addr - 8UL );
      75           0 :   *(ulong*)new = num;
      76           0 :   return (uchar*)new + 8UL;
      77           0 : }
      78             : 
      79             : void
      80           0 : fd_ossl_tile_init( fd_alloc_t * alloc ) {
      81             :   /* OpenSSL's CRYPTO_set_mem_functions is a global operation so it can
      82             :      only be called once for all threads/processes. */
      83           0 :   FD_ONCE_BEGIN {
      84           0 :     if( FD_UNLIKELY( !CRYPTO_set_mem_functions( crypto_malloc, crypto_realloc, crypto_free ) ) ) {
      85           0 :       FD_LOG_ERR(( "CRYPTO_set_mem_functions failed" ));
      86           0 :     }
      87           0 :   } FD_ONCE_END;
      88             : 
      89           0 :   FD_TEST( alloc );
      90           0 :   fd_ossl_alloc = alloc;
      91             : 
      92           0 :   FD_ONCE_BEGIN {
      93           0 :     OPENSSL_init_ssl(
      94           0 :       OPENSSL_INIT_LOAD_SSL_STRINGS |
      95           0 :       OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
      96           0 :       OPENSSL_INIT_NO_LOAD_CONFIG,
      97           0 :       NULL );
      98           0 :   } FD_ONCE_END;
      99           0 : }
     100             : 
     101             : void
     102           0 : fd_ossl_load_certs( SSL_CTX * ssl_ctx ) {
     103           0 :   X509_STORE * ca_certs = X509_STORE_new();
     104           0 :   if( FD_UNLIKELY( !ca_certs ) ) {
     105           0 :     FD_LOG_ERR(( "X509_STORE_new failed" ));
     106           0 :   }
     107             : 
     108           0 :   static char const default_dir[] = "/etc/ssl/certs/";
     109           0 :   DIR * dir = opendir( default_dir );
     110           0 :   if( FD_UNLIKELY( !dir ) ) {
     111           0 :     FD_LOG_ERR(( "opendir(%s) failed (%i-%s)", default_dir, errno, fd_io_strerror( errno ) ));
     112           0 :   }
     113             : 
     114           0 :   struct dirent * entry;
     115           0 :   errno = 0; // clear old value since entry can be NULL when reaching end of directory.
     116           0 :   while( (entry = readdir( dir )) ) {
     117           0 :     if( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) ) continue;
     118             : 
     119           0 :     char cert_path[ PATH_MAX ];
     120           0 :     char * p = fd_cstr_init( cert_path );
     121           0 :     p = fd_cstr_append_text( p, default_dir, sizeof(default_dir)-1 );
     122           0 :     p = fd_cstr_append_cstr_safe( p, entry->d_name, (ulong)(cert_path+sizeof(cert_path)-1) - (ulong)p );
     123           0 :     fd_cstr_fini( p );
     124             : 
     125           0 :     if( !X509_STORE_load_locations( ca_certs, cert_path, NULL ) ) {
     126             :       /* Not all files in /etc/ssl/certs are valid certs, so ignore errors */
     127           0 :       continue;
     128           0 :     }
     129           0 :     errno = 0;
     130           0 :   }
     131             : 
     132           0 :   if( FD_UNLIKELY( errno && errno!=ENOENT ) ) {
     133           0 :     FD_LOG_ERR(( "readdir(%s) failed (%i-%s)", default_dir, errno, fd_io_strerror( errno ) ));
     134           0 :   }
     135             : 
     136           0 :   STACK_OF(X509) * cert_list = X509_STORE_get1_all_certs( ca_certs );
     137           0 :   FD_LOG_INFO(( "Loaded %d CA certs from %s into OpenSSL", sk_X509_num( cert_list ), default_dir ));
     138           0 :   if( fd_log_level_logfile()==0 ) {
     139           0 :     for( int i=0; i<sk_X509_num( cert_list ); i++ ) {
     140           0 :       X509 * cert = sk_X509_value( cert_list, i );
     141           0 :       FD_LOG_DEBUG(( "Loaded CA cert \"%s\"", X509_NAME_oneline( X509_get_subject_name( cert ), NULL, 0 ) ));
     142           0 :     }
     143           0 :   }
     144           0 :   sk_X509_pop_free( cert_list, X509_free );
     145             : 
     146           0 :   SSL_CTX_set_cert_store( ssl_ctx, ca_certs );
     147             : 
     148           0 :   if( FD_UNLIKELY( 0!=closedir( dir ) ) ) {
     149           0 :     FD_LOG_ERR(( "closedir(%s) failed (%i-%s)", default_dir, errno, fd_io_strerror( errno ) ));
     150           0 :   }
     151             : 
     152           0 :   SSL_CTX_set_verify( ssl_ctx, SSL_VERIFY_PEER, NULL );
     153           0 : }
     154             : 
     155             : #endif /* FD_HAS_OPENSSL */

Generated by: LCOV version 1.14