]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add support for 'dohpath' to SVCB (and HTTPS)
authorMark Andrews <marka@isc.org>
Thu, 15 Sep 2022 06:04:43 +0000 (16:04 +1000)
committerMark Andrews <marka@isc.org>
Tue, 4 Oct 2022 03:21:41 +0000 (14:21 +1100)
dohpath is specfied in draft-ietf-add-svcb-dns and has a value
of 7.  It must be a relative path (start with a /), be encoded
as UTF8 and contain the variable dns ({?dns}).

bin/tests/system/checkzone/zones/good-svcb.db
lib/dns/rdata/in_1/svcb_64.c
tests/dns/rdata_test.c

index 7b7b31d6f0a7c81ffe51f4ed5bf59470876e3a7c..df868f3d4ef08e300cd6298a8e7515a780430f9c 100644 (file)
@@ -24,3 +24,4 @@ svcb6         SVCB    6 . mandatory=port,alpn port=60 alpn=h3
 svcb7          SVCB    7 . mandatory=port,alpn port=60 alpn=h1,h3
 svcb8          SVCB    8 . mandatory=port,alpn port=60 alpn="h1\\,h2,h3"
 svcb9          SVCB    0 44._svbc.example.net.
+svcb10         SVCB    7 . alpn="h2,h3" dohpath=/{?dns}
index 7d119d6e4864509ec04b7d8b862ce0bac05595db..e9f43ad1c496325c53f661771db4635750f3b8b0 100644 (file)
@@ -34,13 +34,14 @@ enum encoding {
        sbpr_base64,
        sbpr_empty,
        sbpr_alpn,
-       sbpr_keylist
+       sbpr_keylist,
+       sbpr_dohpath
 };
 static const struct {
        const char *name; /* Restricted to lowercase LDH by registry. */
        unsigned int value;
        enum encoding encoding;
-       bool initial;
+       bool initial; /* Part of the first defined set of encodings. */
 } sbpr[] = {
        { "mandatory", 0, sbpr_keylist, true },
        { "alpn", 1, sbpr_alpn, true },
@@ -49,6 +50,7 @@ static const struct {
        { "ipv4hint", 4, sbpr_ipv4s, true },
        { "ech", 5, sbpr_base64, true },
        { "ipv6hint", 6, sbpr_ipv6s, true },
+       { "dohpath", 7, sbpr_dohpath, false },
 };
 
 static isc_result_t
@@ -147,6 +149,30 @@ svcb_validate(uint16_t key, isc_region_t *region) {
                        case sbpr_text:
                        case sbpr_base64:
                                break;
+                       case sbpr_dohpath:
+                               /*
+                                * Minimum valid dohpath is "/{?dns}" as
+                                * it MUST be relative (leading "/") and
+                                * MUST contain "{?dns}".
+                                */
+                               if (region->length < 7) {
+                                       return (DNS_R_FORMERR);
+                               }
+                               /* MUST be relative */
+                               if (region->base[0] != '/') {
+                                       return (DNS_R_FORMERR);
+                               }
+                               /* MUST be UTF8 */
+                               if (!isc_utf8_valid(region->base,
+                                                   region->length)) {
+                                       return (DNS_R_FORMERR);
+                               }
+                               /* MUST contain "{?dns}" */
+                               if (strnstr((char *)region->base, "{?dns}",
+                                           region->length) == NULL) {
+                                       return (DNS_R_FORMERR);
+                               }
+                               break;
                        case sbpr_empty:
                                if (region->length != 0) {
                                        return (DNS_R_FORMERR);
@@ -252,6 +278,7 @@ svc_fromtext(isc_textregion_t *region, isc_buffer_t *target) {
 
                switch (sbpr[i].encoding) {
                case sbpr_text:
+               case sbpr_dohpath:
                        RETERR(multitxt_fromtext(region, target));
                        break;
                case sbpr_alpn:
@@ -328,6 +355,19 @@ svc_fromtext(isc_textregion_t *region, isc_buffer_t *target) {
                len = isc_buffer_usedlength(target) -
                      isc_buffer_usedlength(&sb) - 2;
                RETERR(uint16_tobuffer(len, &sb)); /* length */
+               switch (sbpr[i].encoding) {
+               case sbpr_dohpath:
+                       /*
+                        * Apply constraints not applied by multitxt_fromtext.
+                        */
+                       keyregion.base = isc_buffer_used(&sb);
+                       keyregion.length = isc_buffer_usedlength(target) -
+                                          isc_buffer_usedlength(&sb);
+                       RETERR(svcb_validate(sbpr[i].value, &keyregion));
+                       break;
+               default:
+                       break;
+               }
                return (ISC_R_SUCCESS);
        }
 
index 0b6c6d73f712f1227f1faff03e57bbe8ec313c13..acd964e4ef179688dff8ad4cc9a865f9d90cc44f 100644 (file)
@@ -2508,7 +2508,7 @@ ISC_RUN_TEST_IMPL(wks) {
 ISC_RUN_TEST_IMPL(https_svcb) {
        /*
         * Known keys: mandatory, apln, no-default-alpn, port,
-        *             ipv4hint, port, ipv6hint.
+        *             ipv4hint, port, ipv6hint, dohpath.
         */
        text_ok_t text_ok[] = {
                /* unknown key invalid */
@@ -2527,9 +2527,9 @@ ISC_RUN_TEST_IMPL(https_svcb) {
                TEXT_INVALID("2 svc.example.net. key=\"2222\""),
                /* zero pad invalid */
                TEXT_INVALID("2 svc.example.net. key07=\"2222\""),
-               TEXT_VALID_LOOP(1, "2 svc.example.net. key7=\"2222\""),
-               TEXT_VALID_LOOPCHG(1, "2 svc.example.net. key7=2222",
-                                  "2 svc.example.net. key7=\"2222\""),
+               TEXT_VALID_LOOP(1, "2 svc.example.net. key8=\"2222\""),
+               TEXT_VALID_LOOPCHG(1, "2 svc.example.net. key8=2222",
+                                  "2 svc.example.net. key8=\"2222\""),
                TEXT_VALID_LOOPCHG(1, "2 svc.example.net. alpn=h2",
                                   "2 svc.example.net. alpn=\"h2\""),
                TEXT_VALID_LOOPCHG(1, "2 svc.example.net. alpn=h3",
@@ -2557,12 +2557,12 @@ ISC_RUN_TEST_IMPL(https_svcb) {
                TEXT_VALID_LOOP(1, "2 svc.example.net. ech=abcdefghijkl"),
                /* bad base64 */
                TEXT_INVALID("2 svc.example.net. ech=abcdefghijklm"),
-               TEXT_VALID_LOOP(1, "2 svc.example.net. key7=\"2222\""),
+               TEXT_VALID_LOOP(1, "2 svc.example.net. key8=\"2222\""),
                /* Out of key order on input (alpn == key1). */
                TEXT_VALID_LOOPCHG(2,
-                                  "2 svc.example.net. key7=\"2222\" alpn=h2",
+                                  "2 svc.example.net. key8=\"2222\" alpn=h2",
                                   "2 svc.example.net. alpn=\"h2\" "
-                                  "key7=\"2222\""),
+                                  "key8=\"2222\""),
                TEXT_VALID_LOOP(1, "2 svc.example.net. key65535=\"2222\""),
                TEXT_INVALID("2 svc.example.net. key65536=\"2222\""),
                TEXT_VALID_LOOP(1, "2 svc.example.net. key10"),
@@ -2593,18 +2593,18 @@ ISC_RUN_TEST_IMPL(https_svcb) {
                TEXT_INVALID("2 svc.example.net. "
                             "mandatory=alpn,,port alpn=h2 port=433"),
                /* mandatory w/ unknown key values */
-               TEXT_VALID_LOOP(2, "2 svc.example.net. mandatory=key7 key7"),
-               TEXT_VALID_LOOP(3, "2 svc.example.net. mandatory=key7,key8 "
-                                  "key7 key8"),
+               TEXT_VALID_LOOP(2, "2 svc.example.net. mandatory=key8 key8"),
+               TEXT_VALID_LOOP(3, "2 svc.example.net. mandatory=key8,key9 "
+                                  "key8 key9"),
                TEXT_VALID_LOOPCHG(
-                       3, "2 svc.example.net. mandatory=key8,key7 key7 key8",
-                       "2 svc.example.net. mandatory=key7,key8 key7 key8"),
+                       3, "2 svc.example.net. mandatory=key9,key8 key8 key9",
+                       "2 svc.example.net. mandatory=key8,key9 key8 key9"),
                TEXT_INVALID("2 svc.example.net. "
-                            "mandatory=key7,key7"),
-               TEXT_INVALID("2 svc.example.net. mandatory=,key7"),
-               TEXT_INVALID("2 svc.example.net. mandatory=key7,"),
+                            "mandatory=key8,key8"),
+               TEXT_INVALID("2 svc.example.net. mandatory=,key8"),
+               TEXT_INVALID("2 svc.example.net. mandatory=key8,"),
                TEXT_INVALID("2 svc.example.net. "
-                            "mandatory=key7,,key7"),
+                            "mandatory=key8,,key8"),
                /* Invalid test vectors */
                TEXT_INVALID("1 foo.example.com. ( key123=abc key123=def )"),
                TEXT_INVALID("1 foo.example.com. mandatory"),
@@ -2617,6 +2617,14 @@ ISC_RUN_TEST_IMPL(https_svcb) {
                TEXT_INVALID("1 foo.example.com. mandatory=mandatory"),
                TEXT_INVALID("1 foo.example.com. ( mandatory=key123,key123 "
                             "key123=abc)"),
+               /* dohpath tests */
+               TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{?dns}",
+                                  "1 example.net. key7=\"/{?dns}\""),
+               TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/some/path{?dns}",
+                                  "1 example.net. key7=\"/some/path{?dns}\""),
+               TEXT_INVALID("1 example.com. dohpath=no-slash"),
+               TEXT_INVALID("1 example.com. dohpath=/{?notdns}"),
+               TEXT_INVALID("1 example.com. dohpath=/notvariable"),
                TEXT_SENTINEL()
 
        };