]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: ssl: reject an embedded NUL in the full-DN ssl_*_dn() fetches
authorWilliam Lallemand <wlallemand@haproxy.com>
Wed, 12 Aug 2026 09:52:46 +0000 (09:52 +0000)
committerWilliam Lallemand <wlallemand@haproxy.com>
Wed, 12 Aug 2026 12:51:25 +0000 (14:51 +0200)
ssl_sock_get_dn_oneline() has the same flaw fixed in ssl_sock_get_dn_entry()
by the previous commit: it copies each DN component's ASN.1-declared bytes
verbatim via memcpy(), keeping an embedded NUL and whatever follows it. It
is used to build the full one-line DN returned by ssl_c_s_dn/ssl_c_i_dn/
ssl_r_dn when no field argument is given, so the same tree-vs-list ACL
match inconsistency applies to it.

Apply the same fix: reject the whole DN (return 0) if any entry has a NUL
followed by a non-NUL byte, and otherwise keep a single trailing NUL and
skip any extra ones.

This should be backported to every stable branch, alongside the previous
commit.

doc/configuration.txt
src/ssl_utils.c

index ad493e013e098c3c3b205528a4c62467aa9256a8..5bdf13d69bcf6e475cbd20da66e3abbf86a16dc3 100644 (file)
@@ -26364,9 +26364,9 @@ ssl_c_i_dn([<entry>[,<occ>[,<format>]]]) : string
   LDAP v3.
   If you'd like to modify the format only you can specify an empty string
   and zero for the first two parameters. Example: ssl_c_i_dn(,0,rfc2253)
-  If the requested entry's ASN.1 value contains an embedded NUL byte
-  followed by other data, it is considered malformed and no data is
-  returned.
+  If the requested entry's ASN.1 value (or, when no <entry> is specified,
+  any entry in the DN) contains an embedded NUL byte followed by other
+  data, it is considered malformed and no data is returned.
 
 ssl_c_key_alg : string
   Returns the name of the algorithm used to generate the key of the certificate
@@ -26416,9 +26416,9 @@ ssl_c_r_dn([<entry>[,<occ>[,<format>]]]) : string
   different protocols. Currently supported is rfc2253 for LDAP v3. If you'd like
   to modify the format only you can specify an empty string and zero for the
   first two parameters. Example: ssl_c_r_dn(,0,rfc2253)
-  If the requested entry's ASN.1 value contains an embedded NUL byte
-  followed by other data, it is considered malformed and no data is
-  returned.
+  If the requested entry's ASN.1 value (or, when no <entry> is specified,
+  any entry in the DN) contains an embedded NUL byte followed by other
+  data, it is considered malformed and no data is returned.
 
 ssl_c_s_dn([<entry>[,<occ>[,<format>]]]) : string
   When the incoming connection was made over an SSL/TLS transport layer,
@@ -26434,9 +26434,9 @@ ssl_c_s_dn([<entry>[,<occ>[,<format>]]]) : string
   LDAP v3.
   If you'd like to modify the format only you can specify an empty string
   and zero for the first two parameters. Example: ssl_c_s_dn(,0,rfc2253)
-  If the requested entry's ASN.1 value contains an embedded NUL byte
-  followed by other data, it is considered malformed and no data is
-  returned.
+  If the requested entry's ASN.1 value (or, when no <entry> is specified,
+  any entry in the DN) contains an embedded NUL byte followed by other
+  data, it is considered malformed and no data is returned.
 
 ssl_c_san : string
   When the incoming connection was made over an SSL/TLS transport layer, and was
@@ -26508,9 +26508,9 @@ ssl_f_i_dn([<entry>[,<occ>[,<format>]]]) : string
   LDAP v3.
   If you'd like to modify the format only you can specify an empty string
   and zero for the first two parameters. Example: ssl_f_i_dn(,0,rfc2253)
-  If the requested entry's ASN.1 value contains an embedded NUL byte
-  followed by other data, it is considered malformed and no data is
-  returned.
+  If the requested entry's ASN.1 value (or, when no <entry> is specified,
+  any entry in the DN) contains an embedded NUL byte followed by other
+  data, it is considered malformed and no data is returned.
 
 ssl_f_key_alg : string
   Returns the name of the algorithm used to generate the key of the certificate
@@ -26541,9 +26541,9 @@ ssl_f_s_dn([<entry>[,<occ>[,<format>]]]) : string
   LDAP v3.
   If you'd like to modify the format only you can specify an empty string
   and zero for the first two parameters. Example: ssl_f_s_dn(,0,rfc2253)
-  If the requested entry's ASN.1 value contains an embedded NUL byte
-  followed by other data, it is considered malformed and no data is
-  returned.
+  If the requested entry's ASN.1 value (or, when no <entry> is specified,
+  any entry in the DN) contains an embedded NUL byte followed by other
+  data, it is considered malformed and no data is returned.
 
 ssl_f_serial : binary
   Returns the serial of the certificate presented by the frontend when the
@@ -26969,9 +26969,9 @@ ssl_s_i_dn([<entry>[,<occ>[,<format>]]]) : string
   LDAP v3.
   If you'd like to modify the format only you can specify an empty string
   and zero for the first two parameters. Example: ssl_s_i_dn(,0,rfc2253)
-  If the requested entry's ASN.1 value contains an embedded NUL byte
-  followed by other data, it is considered malformed and no data is
-  returned.
+  If the requested entry's ASN.1 value (or, when no <entry> is specified,
+  any entry in the DN) contains an embedded NUL byte followed by other
+  data, it is considered malformed and no data is returned.
 
 ssl_s_key_alg : string
   Returns the name of the algorithm used to generate the key of the certificate
@@ -27002,9 +27002,9 @@ ssl_s_s_dn([<entry>[,<occ>[,<format>]]]) : string
   LDAP v3.
   If you'd like to modify the format only you can specify an empty string
   and zero for the first two parameters. Example: ssl_s_s_dn(,0,rfc2253)
-  If the requested entry's ASN.1 value contains an embedded NUL byte
-  followed by other data, it is considered malformed and no data is
-  returned.
+  If the requested entry's ASN.1 value (or, when no <entry> is specified,
+  any entry in the DN) contains an embedded NUL byte followed by other
+  data, it is considered malformed and no data is returned.
 
 ssl_s_serial : binary
   Returns the serial of the certificate presented by the server when the
index 61f410629221c2fe5a0b5a37d1f6cc1a9f5d71be..e48486906b9a967b8be3784f2be2aac9b91d5587 100644 (file)
@@ -301,6 +301,7 @@ int ssl_sock_get_dn_oneline(__X509_NAME_CONST__ X509_NAME *a, struct buffer *out
        __X509_NAME_CONST__ ASN1_OBJECT *obj;
        __X509_NAME_CONST__ ASN1_STRING *data;
        const unsigned char *data_ptr;
+       const unsigned char *nul;
        int data_len;
        int i, n, ln;
        int l = 0;
@@ -320,6 +321,23 @@ int ssl_sock_get_dn_oneline(__X509_NAME_CONST__ X509_NAME *a, struct buffer *out
                data = X509_NAME_ENTRY_get_data(ne);
                data_ptr = ASN1_STRING_get0_data(data);
                data_len = ASN1_STRING_length(data);
+
+               /* reject the whole DN if this entry carries an embedded NUL
+                * (truncation/injection risk for NUL-terminated consumers);
+                * trailing NUL(s) carry nothing after them so they're harmless
+                * padding, just keep one and skip the extra ones
+                */
+               nul = memchr(data_ptr, 0, data_len);
+               if (nul) {
+                       const unsigned char *q;
+
+                       for (q = nul; q < data_ptr + data_len; q++) {
+                               if (*q)
+                                       return 0;
+                       }
+                       data_len = nul - data_ptr + 1;
+               }
+
                n = OBJ_obj2nid(obj);
                if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
                        i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);