From 7c43f85abcabb985873fa09579b077e55d544ea0 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Wed, 12 Aug 2026 09:52:46 +0000 Subject: [PATCH] BUG/MINOR: ssl: reject an embedded NUL in the full-DN ssl_*_dn() fetches 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 | 42 +++++++++++++++++++++--------------------- src/ssl_utils.c | 18 ++++++++++++++++++ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index ad493e013..5bdf13d69 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -26364,9 +26364,9 @@ ssl_c_i_dn([[,[,]]]) : 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 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([[,[,]]]) : 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 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([[,[,]]]) : string When the incoming connection was made over an SSL/TLS transport layer, @@ -26434,9 +26434,9 @@ ssl_c_s_dn([[,[,]]]) : 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 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([[,[,]]]) : 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 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([[,[,]]]) : 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 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([[,[,]]]) : 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 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([[,[,]]]) : 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 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 diff --git a/src/ssl_utils.c b/src/ssl_utils.c index 61f410629..e48486906 100644 --- a/src/ssl_utils.c +++ b/src/ssl_utils.c @@ -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); -- 2.47.3