]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl: porting to X509_STORE_get1_objects() for OpenSSL 4.0
authorWilliam Lallemand <wlallemand@irq6.net>
Mon, 24 Nov 2025 20:44:46 +0000 (21:44 +0100)
committerWilliam Lallemand <wlallemand@haproxy.com>
Thu, 29 Jan 2026 16:08:41 +0000 (17:08 +0100)
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.

include/haproxy/openssl-compat.h
src/ssl_ckch.c
src/ssl_sock.c

index fcd1ca24799539dd3154c6cb25d9c517f6611ae9..fc788aa76977818505d0f48b7e30afc6970cad07 100644 (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
index eb2e9cc846aecda86f79f08b77dbcb26d81b5901..7753fb718ca72de0e5a35d8edffe877ce359d432 100644 (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 */
 }
index ea161a2ba1f766bce9b0da1c61df746a0d8b3817..3540038a25075ce8734099ab546d80b16668b17b 100644 (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);