MEDIUM: ssl: porting to X509_STORE_get1_objects() for OpenSSL 4.0

OpenSSL 4.0 is deprecating X509_STORE_get0_objects().

Every occurence of X509_STORE_get0_objects() was first replaced by
X509_STORE_get1_objects().
This changes the ref count of the STACK_OF(X509_OBJECT) everywhere, and
need it to be sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free) each time.

X509_STORE_get1_objects() is not available in AWS-LC, OpenSSL < 3.2,
LibreSSL and WolfSSL, so we need to still be compatible with get0.
To achieve this, 2 macros were added X509_STORE_getX_objects() and
sk_X509_OBJECT_popX_free(), these macros will use either the get0 or the
get1 macro depending on their availability. In the case of get0,
sk_X509_OBJECT_popX_free() will just do nothing instead of trying to
free.

Don't backport that unless really needed if we want to be compatible
with OpenSSL 4.0. It changes all the refcounts.
This commit is contained in:
William Lallemand 2025-11-24 21:44:46 +01:00 committed by William Lallemand
parent fa094d0b61
commit 23e8ed6ea6
3 changed files with 31 additions and 12 deletions

View file

@ -380,6 +380,14 @@ static inline unsigned long ERR_peek_error_func(const char **func)
#endif
#if (HA_OPENSSL_VERSION_NUMBER >= 0x40000000L) && !defined(OPENSSL_IS_AWSLC) && !defined(LIBRESSL_VERSION_NUMBER) && !defined(USE_OPENSSL_WOLFSSL)
# define X509_STORE_getX_objects(x) X509_STORE_get1_objects(x)
# define sk_X509_OBJECT_popX_free(x, y) sk_X509_OBJECT_pop_free(x,y)
#else
# define X509_STORE_getX_objects(x) X509_STORE_get0_objects(x)
# define sk_X509_OBJECT_popX_free(x, y) ({})
#endif
#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070200fL)
#define __OPENSSL_110_CONST__ const
#else

View file

@ -1345,7 +1345,7 @@ struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
{
struct cafile_entry *dst = NULL;
X509_STORE *store = NULL;
STACK_OF(X509_OBJECT) *objs;
STACK_OF(X509_OBJECT) *objs = NULL;
int i;
if (!src)
@ -1357,7 +1357,7 @@ struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
if (!store)
goto err;
objs = X509_STORE_get0_objects(src->ca_store);
objs = X509_STORE_getX_objects(src->ca_store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
X509 *cert;
X509_CRL *crl;
@ -1385,10 +1385,11 @@ struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
}
}
dst = ssl_store_create_cafile_entry(src->path, store, src->type);
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
return dst;
err:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
X509_STORE_free(store);
ha_free(&dst);
@ -1496,13 +1497,13 @@ end:
*/
int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type, int shuterror)
{
STACK_OF(X509_OBJECT) *objs = NULL;
X509_STORE *store = ssl_store_get0_locations_file(path);
/* If this function is called by the CLI, we should not call the
* X509_STORE_load_locations function because it performs forbidden disk
* accesses. */
if (!store && create_if_none) {
STACK_OF(X509_OBJECT) *objs;
int cert_count = 0;
struct stat buf;
struct cafile_entry *ca_e;
@ -1607,7 +1608,7 @@ scandir_err:
}
}
objs = X509_STORE_get0_objects(store);
objs = X509_STORE_getX_objects(store);
cert_count = sk_X509_OBJECT_num(objs);
if (cert_count == 0) {
if (!shuterror)
@ -1621,9 +1622,11 @@ scandir_err:
}
ebst_insert(&cafile_tree, &ca_e->node);
}
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
return (store != NULL);
err:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
X509_STORE_free(store);
store = NULL;
return 0;
@ -3794,7 +3797,7 @@ static int cli_io_handler_show_cafile_detail(struct appctx *appctx)
struct buffer *out = alloc_trash_chunk();
int i = 0;
X509 *cert;
STACK_OF(X509_OBJECT) *objs;
STACK_OF(X509_OBJECT) *objs = NULL;
int retval = 0;
int ca_index = ctx->ca_index;
int show_all = ctx->show_all;
@ -3820,7 +3823,7 @@ static int cli_io_handler_show_cafile_detail(struct appctx *appctx)
if (!cafile_entry->ca_store)
goto end;
objs = X509_STORE_get0_objects(cafile_entry->ca_store);
objs = X509_STORE_getX_objects(cafile_entry->ca_store);
for (i = ca_index; i < sk_X509_OBJECT_num(objs); i++) {
cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
@ -3843,13 +3846,16 @@ static int cli_io_handler_show_cafile_detail(struct appctx *appctx)
}
end:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 1; /* end, don't come back */
end_no_putchk:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 1;
yield:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
/* save the current state */
ctx->ca_index = i;
free_trash_chunk(out);
@ -3952,9 +3958,10 @@ static int get_certificate_count(struct cafile_entry *cafile_entry)
STACK_OF(X509_OBJECT) *objs;
if (cafile_entry && cafile_entry->ca_store) {
objs = X509_STORE_get0_objects(cafile_entry->ca_store);
objs = X509_STORE_getX_objects(cafile_entry->ca_store);
if (objs)
cert_count = sk_X509_OBJECT_num(objs);
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
}
return cert_count;
}
@ -4484,7 +4491,7 @@ static int cli_io_handler_show_crlfile_detail(struct appctx *appctx)
struct buffer *out = alloc_trash_chunk();
int i;
X509_CRL *crl;
STACK_OF(X509_OBJECT) *objs;
STACK_OF(X509_OBJECT) *objs = NULL;
int retval = 0;
int index = ctx->index;
@ -4509,7 +4516,7 @@ static int cli_io_handler_show_crlfile_detail(struct appctx *appctx)
if (!cafile_entry->ca_store)
goto end;
objs = X509_STORE_get0_objects(cafile_entry->ca_store);
objs = X509_STORE_getX_objects(cafile_entry->ca_store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
crl = X509_OBJECT_get0_X509_CRL(sk_X509_OBJECT_value(objs, i));
if (!crl)
@ -4532,9 +4539,11 @@ end:
goto yield;
end_no_putchk:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 1;
yield:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 0; /* should come back */
}

View file

@ -630,7 +630,7 @@ static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
if (store_ctx && store) {
int i;
X509_OBJECT *obj;
STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
STACK_OF(X509_OBJECT) *objs = X509_STORE_getX_objects(store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
obj = sk_X509_OBJECT_value(objs, i);
switch (X509_OBJECT_get_type(obj)) {
@ -644,6 +644,7 @@ static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
break;
}
}
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
return 1;
}
return 0;
@ -687,7 +688,7 @@ static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
skn = sk_X509_NAME_new_null();
/* take x509 from cafile_tree */
objs = X509_STORE_get0_objects(ca_e->ca_store);
objs = X509_STORE_getX_objects(ca_e->ca_store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
if (!x)
@ -723,6 +724,7 @@ static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
ca_name->xname = xn;
eb64_insert(&ca_name_tree, &ca_name->node);
}
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
ca_e->ca_list = skn;
/* remove temporary ca_name tree */
node = eb64_first(&ca_name_tree);