]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUILD: ssl: make X509_NAME usage OpenSSL 4.0 ready
authorWilliam Lallemand <wlallemand@haproxy.com>
Wed, 11 Mar 2026 14:03:36 +0000 (15:03 +0100)
committerWilliam Lallemand <wlallemand@haproxy.com>
Wed, 11 Mar 2026 16:00:59 +0000 (17:00 +0100)
Starting with OpenSSL 4.0, X509_get_subject_name(), X509_get_issuer_name(),
and X509_CRL_get_issuer() return a const-qualified X509_NAME pointer.
Similarly, X509_NAME_get_entry() returns a const X509_NAME_ENTRY *, and
X509_NAME_ENTRY_get_data() returns a const ASN1_STRING *.

Introduce the __X509_NAME_CONST__ macro (defined to 'const' for OpenSSL
>= 4.0.0, empty for WolfSSL and older OpenSSL version which lacks const
on these APIs) and use it to qualify X509_NAME * variables and the
parameters of the three DN helper functions ssl_sock_get_dn_entry(),
ssl_sock_get_dn_formatted(), and ssl_sock_get_dn_oneline(). This avoids
both const-qualifier warnings on OpenSSL 4.0 and discarded-qualifier
warnings on WolfSSL, without needing explicit casts at call sites.

In ssl_sock.c (ssl_get_client_ca_file) and ssl_gencert.c
(ssl_sock_do_create_cert), a __X509_NAME_CONST__ X509_NAME * variable was
being reused to store the result of X509_NAME_dup() and then passed to
mutating functions (X509_NAME_add_entry_by_txt, X509_NAME_free). Introduce
separate X509_NAME * variables (xn_dup, subject) to hold the mutable
duplicate.

Original patch from Alexandr Nedvedicky <sashan@openssl.org>:
https://www.mail-archive.com/haproxy@formilux.org/msg46696.html

include/haproxy/openssl-compat.h
include/haproxy/ssl_utils.h
src/ssl_ckch.c
src/ssl_gencert.c
src/ssl_sample.c
src/ssl_sock.c
src/ssl_trace.c
src/ssl_utils.c

index fc788aa76977818505d0f48b7e30afc6970cad07..fb859263eb854c41f5254a6c6dd95803f86e275b 100644 (file)
@@ -394,6 +394,12 @@ static inline unsigned long ERR_peek_error_func(const char **func)
 #define __OPENSSL_110_CONST__
 #endif
 
+#if (HA_OPENSSL_VERSION_NUMBER >= 0x40000000L) && (!defined(USE_OPENSSL_WOLFSSL))
+#define __X509_NAME_CONST__ const
+#else
+#define __X509_NAME_CONST__
+#endif
+
 /* ERR_remove_state() was deprecated in 1.0.0 in favor of
  * ERR_remove_thread_state(), which was in turn deprecated in
  * 1.1.0 and does nothing anymore. Let's simply silently kill
index d6649fa9b1c750629d23af24578f5ade0ae8daeb..1d1b169664b0eabf96e75684c91a194b17da1151 100644 (file)
@@ -34,10 +34,10 @@ int cert_get_pkey_algo(X509 *crt, struct buffer *out);
 int ssl_sock_get_serial(X509 *crt, struct buffer *out);
 int ssl_sock_crt2der(X509 *crt, struct buffer *out);
 int ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out);
-int ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
+int ssl_sock_get_dn_entry(__X509_NAME_CONST__ X509_NAME *a, const struct buffer *entry, int pos,
                           struct buffer *out);
-int ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out);
-int ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out);
+int ssl_sock_get_dn_formatted(__X509_NAME_CONST__ X509_NAME *a, const struct buffer *format, struct buffer *out);
+int ssl_sock_get_dn_oneline(__X509_NAME_CONST__ X509_NAME *a, struct buffer *out);
 X509* ssl_sock_get_peer_certificate(SSL *ssl);
 X509* ssl_sock_get_verified_chain_root(SSL *ssl);
 unsigned int openssl_version_parser(const char *version);
index 787e289d9de762fc1d30b4b3bb5b7ffc53124dcb..c03e95d36a476da65c9545a10011010cc74e6ee8 100644 (file)
@@ -2126,7 +2126,7 @@ static int show_cert_detail(X509 *cert, STACK_OF(X509) *chain, struct issuer_cha
        int i;
        int write = -1;
        unsigned int len = 0;
-       X509_NAME *name = NULL;
+       __X509_NAME_CONST__ X509_NAME *name = NULL;
 
        if (!tmp)
                return -1;
@@ -4412,7 +4412,7 @@ static int show_crl_detail(X509_CRL *crl, struct buffer *out)
        BIO *bio = NULL;
        struct buffer *tmp = alloc_trash_chunk();
        long version;
-       X509_NAME *issuer;
+       __X509_NAME_CONST__ X509_NAME *issuer;
        int write = -1;
 #ifndef USE_OPENSSL_WOLFSSL
        STACK_OF(X509_REVOKED) *rev = NULL;
index ef6922d356dd0652154fb86eb103ba2a4d11d694..d5d710daad628fd8d68ac99712bdf39b21a1bb08 100644 (file)
@@ -92,7 +92,8 @@ static SSL_CTX *ssl_sock_do_create_cert(const char *servername, struct bind_conf
        EVP_PKEY     *pkey    = NULL;
        SSL          *tmp_ssl = NULL;
        CONF         *ctmp    = NULL;
-       X509_NAME    *name;
+       __X509_NAME_CONST__ X509_NAME *name;
+       X509_NAME    *subject = NULL;
        const EVP_MD *digest;
        X509V3_CTX    ctx;
        unsigned int  i;
@@ -140,21 +141,21 @@ static SSL_CTX *ssl_sock_do_create_cert(const char *servername, struct bind_conf
                goto mkcert_error;
 
        /* Set the subject name using the same, but the CN */
-       name = X509_NAME_dup(name);
+       subject = X509_NAME_dup(name);
 
        if (strlen(servername) <= 64) {
-               if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
+               if (X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC,
                                              (const unsigned char *)servername,
                                              -1, -1, 0) != 1) {
-                       X509_NAME_free(name);
+                       X509_NAME_free(subject);
                        goto mkcert_error;
                }
        }
-       if (X509_set_subject_name(newcrt, name) != 1) {
-               X509_NAME_free(name);
+       if (X509_set_subject_name(newcrt, subject) != 1) {
+               X509_NAME_free(subject);
                goto mkcert_error;
        }
-       X509_NAME_free(name);
+       X509_NAME_free(subject);
 
        /* Add x509v3 extensions as specified */
        ctmp = NCONF_new(NULL);
index b2740f309feeb07c5bffd6e4e5d21efffde682b8..fdbbdd3e878219af5a7d4b60b35fda7be593f8ec 100644 (file)
@@ -779,7 +779,7 @@ static int
 smp_fetch_ssl_r_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
        X509 *crt = NULL;
-       X509_NAME *name;
+       __X509_NAME_CONST__ X509_NAME *name;
        int ret = 0;
        struct buffer *smp_trash;
        struct connection *conn;
@@ -1113,7 +1113,7 @@ smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw,
        int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
        int conn_server = (kw[4] == 's') ? 1 : 0;
        X509 *crt = NULL;
-       X509_NAME *name;
+       __X509_NAME_CONST__ X509_NAME *name;
        int ret = 0;
        struct buffer *smp_trash;
        struct connection *conn;
@@ -1309,7 +1309,7 @@ smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw,
        int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
        int conn_server = (kw[4] == 's') ? 1 : 0;
        X509 *crt = NULL;
-       X509_NAME *name;
+       __X509_NAME_CONST__ X509_NAME *name;
        int ret = 0;
        struct buffer *smp_trash;
        struct connection *conn;
index aeb408ffa14bda62ea8c5ad1573948b3a3e4c03a..2e38dc0649d68f04a81198da3de9f217f19c6113 100644 (file)
@@ -691,7 +691,8 @@ static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
                STACK_OF(X509_OBJECT) *objs;
                STACK_OF(X509_NAME) *skn;
                X509 *x;
-               X509_NAME *xn;
+               __X509_NAME_CONST__ X509_NAME *xn;
+               X509_NAME *xn_dup;
 
                skn = sk_X509_NAME_new_null();
                /* take x509 from cafile_tree */
@@ -716,19 +717,19 @@ static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
                        if (ca_name)
                                continue;
                        ca_name = calloc(1, sizeof *ca_name);
-                       xn = X509_NAME_dup(xn);
+                       xn_dup = X509_NAME_dup(xn);
                        if (!ca_name ||
-                           !xn ||
-                           !sk_X509_NAME_push(skn, xn)) {
+                           !xn_dup ||
+                           !sk_X509_NAME_push(skn, xn_dup)) {
                                    free(ca_name);
-                                   X509_NAME_free(xn);
+                                   X509_NAME_free(xn_dup);
                                    sk_X509_NAME_pop_free(skn, X509_NAME_free);
                                    sk_X509_NAME_free(skn);
                                    skn = NULL;
                                    break;
                        }
                        ca_name->node.key = key;
-                       ca_name->xname = xn;
+                       ca_name->xname = xn_dup;
                        eb64_insert(&ca_name_tree, &ca_name->node);
                }
                sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
@@ -3151,7 +3152,7 @@ int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct
        SSL_CTX *ctx;
        int i;
        int order = 0;
-       X509_NAME *xname;
+       __X509_NAME_CONST__ X509_NAME *xname;
        char *str;
        EVP_PKEY *pkey;
        struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
@@ -3243,8 +3244,8 @@ int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct
                xname = X509_get_subject_name(data->cert);
                i = -1;
                while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
-                       X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
-                       ASN1_STRING *value;
+                       __X509_NAME_CONST__ X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
+                       __X509_NAME_CONST__ ASN1_STRING *value;
 
                        value = X509_NAME_ENTRY_get_data(entry);
                        if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
@@ -4897,7 +4898,7 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
        X509 *cert;
        STACK_OF(GENERAL_NAME) *alt_names;
        int i;
-       X509_NAME *cert_subject;
+       __X509_NAME_CONST__ X509_NAME *cert_subject;
        char *str;
 
        if (ok == 0)
@@ -4963,8 +4964,8 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
        cert_subject = X509_get_subject_name(cert);
        i = -1;
        while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
-               X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
-               ASN1_STRING *value;
+               __X509_NAME_CONST__ X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
+               __X509_NAME_CONST__ ASN1_STRING *value;
                value = X509_NAME_ENTRY_get_data(entry);
                if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
                        ok = ssl_sock_srv_hostcheck(str, servername);
@@ -7637,7 +7638,7 @@ int ssl_sock_get_remote_common_name(struct connection *conn,
 {
        struct ssl_sock_ctx *ctx = conn_get_ssl_sock_ctx(conn);
        X509 *crt = NULL;
-       X509_NAME *name;
+       __X509_NAME_CONST__ X509_NAME *name;
        const char find_cn[] = "CN";
        const struct buffer find_cn_chunk = {
                .area = (char *)&find_cn,
@@ -7737,7 +7738,7 @@ int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char
 int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
 {
        X509 *ca;
-       X509_NAME *name = NULL;
+       __X509_NAME_CONST__ X509_NAME *name = NULL;
        ASN1_OCTET_STRING *skid = NULL;
        STACK_OF(X509) *chain = NULL;
        struct issuer_chain *issuer;
index ae5a07233108086adfc455ab7f1e36db3f3eeb9f..96cb8a2a7443097f33ae6c3e501fb5b57e8795d2 100644 (file)
@@ -140,7 +140,7 @@ static void ssl_trace(enum trace_level level, uint64_t mask, const struct trace_
                                X509 *crt = SSL_get_certificate(ssl);
 
                                if (crt) {
-                                       X509_NAME *name = X509_get_subject_name(crt);
+                                       __X509_NAME_CONST__ X509_NAME *name = X509_get_subject_name(crt);
                                        if (name)
                                                chunk_appendf(&trace_buf, " subject=\"%s\"",
                                                              X509_NAME_oneline(name, 0, 0));
index 6ecd0303902b5c92b9dbfd320af5291a450bd598..836e44cc21b3a8f070fd1649edabbacb4c8c360d 100644 (file)
@@ -187,12 +187,12 @@ int ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
 /* Extract an entry from a X509_NAME and copy its value to an output chunk.
  * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
  */
-int ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
+int ssl_sock_get_dn_entry(__X509_NAME_CONST__ X509_NAME *a, const struct buffer *entry, int pos,
                           struct buffer *out)
 {
-       X509_NAME_ENTRY *ne;
-       ASN1_OBJECT *obj;
-       ASN1_STRING *data;
+       __X509_NAME_CONST__ X509_NAME_ENTRY *ne;
+       __X509_NAME_CONST__ ASN1_OBJECT *obj;
+       __X509_NAME_CONST__ ASN1_STRING *data;
        const unsigned char *data_ptr;
        int data_len;
        int i, j, n;
@@ -249,7 +249,7 @@ int ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
  * Currently supports rfc2253 for returning LDAP V3 DNs.
  * Returns 1 if dn entries exist, 0 if no dn entry was found.
  */
-int ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
+int ssl_sock_get_dn_formatted(__X509_NAME_CONST__ X509_NAME *a, const struct buffer *format, struct buffer *out)
 {
        BIO *bio = NULL;
        int ret = 0;
@@ -279,11 +279,11 @@ out:
 /* Extract and format full DN from a X509_NAME and copy result into a chunk
  * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
  */
-int ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
+int ssl_sock_get_dn_oneline(__X509_NAME_CONST__ X509_NAME *a, struct buffer *out)
 {
-       X509_NAME_ENTRY *ne;
-       ASN1_OBJECT *obj;
-       ASN1_STRING *data;
+       __X509_NAME_CONST__ X509_NAME_ENTRY *ne;
+       __X509_NAME_CONST__ ASN1_OBJECT *obj;
+       __X509_NAME_CONST__ ASN1_STRING *data;
        const unsigned char *data_ptr;
        int data_len;
        int i, n, ln;