]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: ssl: accept integer group IDs in curve2name
authorWilliam Lallemand <wlallemand@irq6.net>
Tue, 6 Oct 2026 13:26:21 +0000 (15:26 +0200)
committerWilliam Lallemand <wlallemand@irq6.net>
Tue, 6 Oct 2026 13:39:56 +0000 (15:39 +0200)
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.

doc/configuration.txt
reg-tests/ssl/curve2name.vtc
src/ssl_utils.c

index a2d27804bb097ab37ea4e780737bc13cd5e0fae8..b814e5bae288185fad4d81480a6364e147865c94 100644 (file)
@@ -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([<avalanche>])
   also "djb2", "sdbm", "wt6", "crc32" and the "hash-type" directive.
 
 curve2name(<format>)
-  Converts a curve name to the naming convention selected by <format>. The
-  following formats are supported:
+  Converts a curve name or an integer TLS Supported Group identifier to the
+  naming convention selected by <format>. 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(<format>)
   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
index d6a92fdb7ae69c9d4bed0bd7baedb4bdd9e58097..1a2997b7d5a07a1457e5fe04e41845abe2806ed0 100644 (file)
@@ -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
index 15f190431202a624c8d72dc3b3abb82559922c3d..431b5d47c6b456d977fca9a6f80a7a1fea101601 100644 (file)
@@ -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 },
 }};