Skip to content

Commit

Permalink
feat: load full certificate bundles from NODE_EXTRA_CA_CERTS
Browse files Browse the repository at this point in the history
  • Loading branch information
ShlomoCode committed Jan 28, 2025
1 parent c08f4ab commit 98b16af
Showing 1 changed file with 41 additions and 30 deletions.
71 changes: 41 additions & 30 deletions packages/bun-usockets/src/crypto/root_certs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <string.h>
#include <openssl/err.h>

static const int root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]);

// This callback is used to avoid the default passphrase callback in OpenSSL
Expand All @@ -20,7 +22,7 @@ int us_no_password_callback(char *buf, int size, int rwflag, void *u) {
static X509 *
us_ssl_ctx_get_X509_without_callback_from(struct us_cert_string_t content) {
X509 *x = NULL;
BIO *in;
BIO *in = NULL;

ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()

Expand All @@ -36,48 +38,59 @@ us_ssl_ctx_get_X509_without_callback_from(struct us_cert_string_t content) {
goto end;
}

end:
// NOTE: PEM_read_bio_X509 allocates, so input BIO must be freed.
BIO_free(in);
return x;
end:
X509_free(x);
BIO_free(in);
return NULL;
}

static X509 *
us_ssl_ctx_get_X509_without_callback_from_file(const char *filename) {
static STACK_OF(X509) *us_ssl_ctx_load_all_certs_from_file(const char *filename) {
BIO *in = NULL;
STACK_OF(X509) *certs = NULL;
X509 *x = NULL;
BIO *in;

ERR_clear_error(); // clear error stack for SSL_CTX_use_certificate()

in = BIO_new(BIO_s_file());
in = BIO_new_file(filename, "r");
if (in == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
goto end;
}

if (BIO_read_filename(in, filename) <= 0) {
OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
certs = sk_X509_new_null();
if (certs == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto end;
}

x = PEM_read_bio_X509(in, NULL, us_no_password_callback, NULL);
if (x == NULL) {
while ((x = PEM_read_bio_X509(in, NULL, us_no_password_callback, NULL))) {
if (!sk_X509_push(certs, x)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
X509_free(x);
goto end;
}
}

if (sk_X509_num(certs) == 0) {
OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
goto end;
}
return x;

end:
X509_free(x);
BIO_free(in);
return NULL;
if (in) BIO_free(in);
if (certs && sk_X509_num(certs) == 0) {
sk_X509_pop_free(certs, X509_free);
certs = NULL;
}
return certs;
}

static void us_internal_init_root_certs(X509 *root_cert_instances[sizeof(root_certs) / sizeof(root_certs[0])], X509 *&root_extra_cert_instances) {
static void us_internal_init_root_certs(
X509 *root_cert_instances[root_certs_size],
STACK_OF(X509) *&root_extra_cert_instances) {
static std::atomic_flag root_cert_instances_lock = ATOMIC_FLAG_INIT;
static std::atomic_bool root_cert_instances_initialized = 0;

if (std::atomic_load(&root_cert_instances_initialized) == 1)
return;

Expand All @@ -93,12 +106,8 @@ static void us_internal_init_root_certs(X509 *root_cert_instances[sizeof(root_ce

// get extra cert option from environment variable
const char *extra_cert = getenv("NODE_EXTRA_CA_CERTS");
if (extra_cert) {
size_t length = strlen(extra_cert);
if (length > 0) {
root_extra_cert_instances =
us_ssl_ctx_get_X509_without_callback_from_file(extra_cert);
}
if (extra_cert && extra_cert[0]) {
root_extra_cert_instances = us_ssl_ctx_load_all_certs_from_file(extra_cert);
}
}

Expand All @@ -122,9 +131,8 @@ extern "C" X509_STORE *us_get_default_ca_store() {
return NULL;
}

static X509 *root_cert_instances[sizeof(root_certs) / sizeof(root_certs[0])] = {
NULL};
static X509 *root_extra_cert_instances = NULL;
static X509 *root_cert_instances[root_certs_size] = {NULL};
static STACK_OF(X509) *root_extra_cert_instances = NULL;

us_internal_init_root_certs(root_cert_instances, root_extra_cert_instances);

Expand All @@ -138,8 +146,11 @@ extern "C" X509_STORE *us_get_default_ca_store() {
}

if (root_extra_cert_instances) {
X509_up_ref(root_extra_cert_instances);
X509_STORE_add_cert(store, root_extra_cert_instances);
for (int i = 0; i < sk_X509_num(root_extra_cert_instances); i++) {
X509 *cert = sk_X509_value(root_extra_cert_instances, i);
X509_up_ref(cert);
X509_STORE_add_cert(store, cert);
}
}

return store;
Expand Down

0 comments on commit 98b16af

Please sign in to comment.