From: TCY16 Date: Mon, 15 Aug 2022 12:36:35 +0000 (+0200) Subject: add dohpath parsing X-Git-Tag: release-1.18.0rc1~24^2~18^2~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6e31d1f5beb542e81d722f39cae92e59b95fad5a;p=thirdparty%2Funbound.git add dohpath parsing --- diff --git a/sldns/str2wire.c b/sldns/str2wire.c index 303d49ba6..a620738c2 100644 --- a/sldns/str2wire.c +++ b/sldns/str2wire.c @@ -1150,6 +1150,11 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len) return SVCB_KEY_IPV6HINT; break; + case sizeof("dohpath")-1: + if (!strncmp(key, "dohpath", sizeof("dohpath")-1)) + return SVCB_KEY_DOHPATH; + break; + case sizeof("ech")-1: if (!strncmp(key, "ech", sizeof("ech")-1)) return SVCB_KEY_ECH; @@ -1515,6 +1520,40 @@ sldns_str2wire_svcbparam_alpn_value(const char* val, return LDNS_WIREPARSE_ERR_OK; } +static int +sldns_str2wire_svcbparam_dohpath_value(const char* val, + uint8_t* rd, size_t* rd_len) +{ + size_t val_len; + + /* RFC6570#section-2.1 + * "The characters outside of expressions in a URI Template string are + * intended to be copied literally" + * Practically this means we do not have to look for "double escapes" + * like in the alpn value list. + */ + + val_len = strlen(val); + + if (*rd_len < 4 + val_len) { + return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; + } + + /* draft-ietf-add-svcb-dns-06#section-5.1 + * The URI Template MUST contain a "dns" variable + */ + if (!(strstr(val, "?dns"))) { + return LDNS_WIREPARSE_ERR_SVCB_NO_DNS_VAR_IN_DOHPATH; + } + + sldns_write_uint16(rd, SVCB_KEY_DOHPATH); + sldns_write_uint16(rd + 2, val_len); + memcpy(rd + 4, val, val_len); + *rd_len = 4 + val_len; + + return LDNS_WIREPARSE_ERR_OK; +} + static int sldns_str2wire_svcparam_value(const char *key, size_t key_len, const char *val, uint8_t* rd, size_t* rd_len) @@ -1535,6 +1574,7 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len, case SVCB_KEY_PORT: case SVCB_KEY_IPV4HINT: case SVCB_KEY_IPV6HINT: + case SVCB_KEY_DOHPATH: return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM; #endif default: @@ -1566,6 +1606,8 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len, return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len); case SVCB_KEY_ALPN: return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len); + case SVCB_KEY_DOHPATH: + return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len); default: str_len = strlen(val); if (*rd_len < 4 + str_len) diff --git a/sldns/str2wire.h b/sldns/str2wire.h index baee4236f..18cfc4fa7 100644 --- a/sldns/str2wire.h +++ b/sldns/str2wire.h @@ -38,7 +38,8 @@ struct sldns_struct_lookup_table; #define SVCB_KEY_IPV4HINT 4 #define SVCB_KEY_ECH 5 #define SVCB_KEY_IPV6HINT 6 -#define SVCPARAMKEY_COUNT 7 +#define SVCB_KEY_DOHPATH 7 +#define SVCPARAMKEY_COUNT 8 #define MAX_NUMBER_OF_SVCPARAMS 64 @@ -234,7 +235,9 @@ uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len); #define LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES 383 #define LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE 384 #define LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE 385 -#define LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA 386 +#define LDNS_WIREPARSE_ERR_SVCB_NO_DNS_VAR_IN_DOHPATH 386 +#define LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA 387 + /** * Get reference to a constant string for the (parse) error. diff --git a/sldns/wire2str.c b/sldns/wire2str.c index 74d1b62df..5740aee77 100644 --- a/sldns/wire2str.c +++ b/sldns/wire2str.c @@ -171,6 +171,8 @@ static sldns_lookup_table sldns_wireparse_errors_data[] = { "Alpn strings need to be smaller than 255 chars"}, { LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE, "No-default-alpn should not have a value" }, + { LDNS_WIREPARSE_ERR_SVCB_NO_DNS_VAR_IN_DOHPATH, + "Dohpath must have '?dns' in the URI template variable" }, { LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA, "General SVCParam error" }, { 0, NULL } @@ -224,7 +226,7 @@ sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data; /* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */ const char *svcparamkey_strs[] = { "mandatory", "alpn", "no-default-alpn", "port", - "ipv4hint", "ech", "ipv6hint" + "ipv4hint", "ech", "ipv6hint", "dohpath" }; char* sldns_wire2str_pkt(uint8_t* data, size_t len) @@ -1144,6 +1146,29 @@ static int sldns_wire2str_svcparam_ech2str(char** s, return w + size; } +static int sldns_wire2str_svcparam_dohpath2str(char** s, + size_t* slen, uint16_t data_len, uint8_t* data) +{ + int w = 0; + uint16_t i; + + assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */ + + w += sldns_str_print(s, slen, "=\""); + + /* RC6570#section-2.1 specifies that the '\' (and other non-letter + * characters in the URI) are "intended to be copied literally" */ + for (i = 0; i < data_len; i++) { + // @TODO do a check like isprint()? + + w += sldns_str_print(s, slen, "%c", data[i]); + } + + w += sldns_str_print(s, slen, "\""); + + return w; +} + int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) { uint8_t ch; @@ -1174,6 +1199,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl case SVCB_KEY_IPV4HINT: case SVCB_KEY_IPV6HINT: case SVCB_KEY_MANDATORY: + case SVCB_KEY_DOHPATH: return -1; default: return written_chars; @@ -1201,6 +1227,9 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl case SVCB_KEY_ECH: r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d); break; + case SVCB_KEY_DOHPATH: + r = sldns_wire2str_svcparam_dohpath2str(s, slen, data_len, *d); + break; default: r = sldns_str_print(s, slen, "=\"");