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 },
{ "ipv4hint", 4, sbpr_ipv4s, true },
{ "ech", 5, sbpr_base64, true },
{ "ipv6hint", 6, sbpr_ipv6s, true },
+ { "dohpath", 7, sbpr_dohpath, false },
};
static isc_result_t
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);
switch (sbpr[i].encoding) {
case sbpr_text:
+ case sbpr_dohpath:
RETERR(multitxt_fromtext(region, target));
break;
case sbpr_alpn:
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);
}
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 */
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",
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"),
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"),
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()
};