From ff7e3008c50903c9b42a5628ce7dd570ce688889 Mon Sep 17 00:00:00 2001 From: Alexandr Nedvedicky Date: Wed, 25 Feb 2026 20:10:53 +0100 Subject: [PATCH] BUILD: make HAProxy OpenSSL 4.0 ready Updates HA-proxy, so it builds with OpenSSL 4.0. The diff below has been compile tested so far. It builds with OpenSSL master as well as OpenSSL 3.5. more details on changes can be found here: OpenSSL 4.0 makes ASN1_STRING (et. al.) opaque. [ https://github.com/openssl/openssl/pull/29862 ] Starting OpenSSL 4.0 X509_get_subject_name() (et. al.) rturns const objects now. [ https://github.com/openssl/openssl/pull/29468 ] --- include/haproxy/ssl_utils.h | 6 ++--- src/ssl_sample.c | 4 +-- src/ssl_utils.c | 49 ++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/include/haproxy/ssl_utils.h b/include/haproxy/ssl_utils.h index d6649fa9b..d4751c5fc 100644 --- a/include/haproxy/ssl_utils.h +++ b/include/haproxy/ssl_utils.h @@ -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(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(const X509_NAME *a, const struct buffer *format, struct buffer *out); +int ssl_sock_get_dn_oneline(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); diff --git a/src/ssl_sample.c b/src/ssl_sample.c index 5a3783a73..072bd0346 100644 --- a/src/ssl_sample.c +++ b/src/ssl_sample.c @@ -774,7 +774,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; + const X509_NAME *name; int ret = 0; struct buffer *smp_trash; struct connection *conn; @@ -1108,7 +1108,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; + const X509_NAME *name; int ret = 0; struct buffer *smp_trash; struct connection *conn; diff --git a/src/ssl_utils.c b/src/ssl_utils.c index eadcec24b..029ae73d0 100644 --- a/src/ssl_utils.c +++ b/src/ssl_utils.c @@ -74,11 +74,12 @@ int ssl_sock_get_serial(X509 *crt, struct buffer *out) if (!serial) return 0; - if (out->size < serial->length) + if (out->size < ASN1_STRING_length(serial)) return -1; - memcpy(out->area, serial->data, serial->length); - out->data = serial->length; + out->data = ASN1_STRING_length(serial); + memcpy(out->area, ASN1_STRING_get0_data(serial), out->data); + return 1; } @@ -110,32 +111,34 @@ int ssl_sock_crt2der(X509 *crt, struct buffer *out) */ int ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out) { - if (tm->type == V_ASN1_GENERALIZEDTIME) { - ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm; + const unsigned char *data; - if (gentm->length < 12) + if (ASN1_STRING_type(tm) == V_ASN1_GENERALIZEDTIME) { + data = ASN1_STRING_get0_data(tm); + + if (ASN1_STRING_length(tm) < 12) return 0; - if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30) + if (data[0] != 0x32 || data[1] != 0x30) return 0; - if (out->size < gentm->length-2) + if (out->size < ASN1_STRING_length(tm) - 2) return -1; - memcpy(out->area, gentm->data+2, gentm->length-2); - out->data = gentm->length-2; + out->data = ASN1_STRING_length(tm) - 2; + memcpy(out->area, data + 2, out->data); return 1; } else if (tm->type == V_ASN1_UTCTIME) { - ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm; + data = ASN1_STRING_get0_data(tm); - if (utctm->length < 10) + if (ASN1_STRING_length(tm) < 10) return 0; - if (utctm->data[0] >= 0x35) + if (data[0] >= 0x35) return 0; - if (out->size < utctm->length) + if (out->size < ASN1_STRING_length(tm)) return -1; - memcpy(out->area, utctm->data, utctm->length); - out->data = utctm->length; + out->data = ASN1_STRING_length(tm); + memcpy(out->area, data, out->data); return 1; } @@ -145,7 +148,7 @@ 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(const X509_NAME *a, const struct buffer *entry, int pos, struct buffer *out) { X509_NAME_ENTRY *ne; @@ -207,7 +210,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(const X509_NAME *a, const struct buffer *format, struct buffer *out) { BIO *bio = NULL; int ret = 0; @@ -237,7 +240,7 @@ 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(const X509_NAME *a, struct buffer *out) { X509_NAME_ENTRY *ne; ASN1_OBJECT *obj; @@ -629,16 +632,16 @@ INITCALL0(STG_REGISTER, init_x509_v_err_tab); long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d) { long epoch; - char *p, *end; + const unsigned char *p, *end; const unsigned short month_offset[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; unsigned long year, month; - if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1; + if (!d || (ASN1_STRING_type(d) != V_ASN1_GENERALIZEDTIME)) return -1; - p = (char *)d->data; - end = p + d->length; + p = ASN1_STRING_get0_data(d); + end = p + ASN1_STRING_length(d); if (end - p < 4) return -1; year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';