From: William Lallemand Date: Tue, 6 Oct 2026 13:26:21 +0000 (+0200) Subject: MINOR: ssl: accept integer group IDs in curve2name X-Git-Tag: v3.5-dev9~184 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=306db36ec01ba6268574092b5e38c7a2cb5d1695;p=haproxy.git MINOR: ssl: accept integer group IDs in curve2name Allow curve2name to convert integer TLS Supported Group identifiers in addition to curve names. Register the converter with SMP_T_ANY to preserve the input type, and accept only integer and string samples. Return unknown IDs, or IDs without a name in the requested convention, as decimal strings. Preserve the existing fallback for string inputs. Document binary group extraction and extend regression coverage for integer IDs, missing names, unknown IDs and values outside the TLS identifier range. The build and converter regression test pass. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index a2d27804b..b814e5bae 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -21599,7 +21599,7 @@ concat([start[,var[,end]]]) string string cpl integer integer crc32([avalanche]) binary integer crc32c([avalanche]) binary integer -curve2name(format) string string +curve2name(format) any string cut_crlf string string da-csv-conv(prop[,prop*]) string string date string integer @@ -22041,8 +22041,8 @@ crc32c([]) also "djb2", "sdbm", "wt6", "crc32" and the "hash-type" directive. curve2name() - Converts a curve name to the naming convention selected by . The - following formats are supported: + Converts a curve name or an integer TLS Supported Group identifier to the + naming convention selected by . The following formats are supported: - iana: registered TLS group name, such as "secp256r1" or "x25519". Names are listed in the IANA TLS Supported Groups registry: @@ -22055,12 +22055,15 @@ curve2name() converter requires SSL support. The original input is returned unchanged if it is unknown or the curve has - no name in the requested convention. For example, + no name in the requested convention. Integer inputs are returned as decimal + strings in these cases. For example, "prime256v1,curve2name(iana)" produces "secp256r1", and "secp256r1,curve2name(nist)" produces "P-256". Example: http-response set-header X-Curve %[ssl_fc_curve,curve2name(iana)] + # Convert an extracted two-byte TLS group identifier (0x0017 = 23). + http-response set-header X-Group %[bin(0017),hex,hex2i,curve2name(iana)] cut_crlf Cuts the string representation of the input sample on the first carriage diff --git a/reg-tests/ssl/curve2name.vtc b/reg-tests/ssl/curve2name.vtc index d6a92fdb7..1a2997b7d 100644 --- a/reg-tests/ssl/curve2name.vtc +++ b/reg-tests/ssl/curve2name.vtc @@ -13,7 +13,7 @@ haproxy h1 -conf { frontend fe bind "fd@${fe}" - http-request return status 200 hdr x-iana %[req.hdr(curve),curve2name(IANA)] hdr x-ansi %[req.hdr(curve),curve2name(ANSI)] hdr x-nist %[req.hdr(curve),curve2name(NiSt)] + http-request return status 200 hdr x-iana %[req.hdr(curve),curve2name(IANA)] hdr x-ansi %[req.hdr(curve),curve2name(ANSI)] hdr x-nist %[req.hdr(curve),curve2name(NiSt)] hdr x-id-iana %[req.hdr(group),add(0),curve2name(IANA)] hdr x-id-ansi %[req.hdr(group),add(0),curve2name(ANSI)] hdr x-id-nist %[req.hdr(group),add(0),curve2name(NiSt)] hdr x-bin %[bin(0017),hex,hex2i,curve2name(iana)] } -start client c1 -connect ${h1_fe_sock} { @@ -55,4 +55,31 @@ client c1 -connect ${h1_fe_sock} { expect resp.http.x-iana == "secp256r1-extra" expect resp.http.x-ansi == "secp256r1-extra" expect resp.http.x-nist == "secp256r1-extra" + + txreq -hdr "group: 23" + rxresp + expect resp.http.x-id-iana == "secp256r1" + expect resp.http.x-id-ansi == "prime256v1" + expect resp.http.x-id-nist == "P-256" + expect resp.http.x-bin == "secp256r1" + + txreq -hdr "group: 29" + rxresp + expect resp.http.x-id-iana == "x25519" + expect resp.http.x-id-ansi == "29" + expect resp.http.x-id-nist == "29" + + txreq -hdr "group: 65535" + rxresp + expect resp.http.x-id-iana == "65535" + expect resp.http.x-id-ansi == "65535" + expect resp.http.x-id-nist == "65535" + + txreq -hdr "group: -1" + rxresp + expect resp.http.x-id-iana == "-1" + + txreq -hdr "group: 4294967319" + rxresp + expect resp.http.x-id-iana == "4294967319" } -run diff --git a/src/ssl_utils.c b/src/ssl_utils.c index 15f190431..431b5d47c 100644 --- a/src/ssl_utils.c +++ b/src/ssl_utils.c @@ -1186,14 +1186,25 @@ static int sample_conv_curve2name(const struct arg *args, struct sample *smp, const char *format = args[0].data.str.area; const char *name = NULL; - for (item = curves_list; item->curve_id; item++) { - if (curve_name_matches(&smp->data.u.str, item->ansi) || - curve_name_matches(&smp->data.u.str, item->iana) || - curve_name_matches(&smp->data.u.str, item->nist)) - break; + if (smp->data.type == SMP_T_SINT) { + for (item = curves_list; item->curve_id; item++) { + if (item->curve_id == smp->data.u.sint) + break; + } + } + else if (smp->data.type == SMP_T_STR) { + for (item = curves_list; item->curve_id; item++) { + if (curve_name_matches(&smp->data.u.str, item->ansi) || + curve_name_matches(&smp->data.u.str, item->iana) || + curve_name_matches(&smp->data.u.str, item->nist)) + break; + } } + else + return 0; + if (!item->curve_id) - return 1; + return sample_convert(smp, SMP_T_STR); /* Resolve compatibility aliases to the first entry for the group. */ for (canonical = curves_list; canonical->curve_id != item->curve_id; canonical++) @@ -1207,8 +1218,9 @@ static int sample_conv_curve2name(const struct arg *args, struct sample *smp, name = canonical->nist; if (!name) - return 1; + return sample_convert(smp, SMP_T_STR); + smp->data.type = SMP_T_STR; smp->data.u.str.area = (char *)name; smp->data.u.str.data = strlen(name); smp->data.u.str.size = 0; @@ -1216,8 +1228,9 @@ static int sample_conv_curve2name(const struct arg *args, struct sample *smp, return 1; } +/* ANY preserves the input type; curve2name only accepts integers and strings. */ static struct sample_conv_kw_list curve_conv_kws = { ILH, { - { "curve2name", sample_conv_curve2name, ARG1(1,STR), check_curve2name, SMP_T_STR, SMP_T_STR }, + { "curve2name", sample_conv_curve2name, ARG1(1,STR), check_curve2name, SMP_T_ANY, SMP_T_STR }, { NULL, NULL, 0, 0, 0 }, }};