]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
add dohpath parsing
authorTCY16 <tom@nlnetlabs.nl>
Mon, 15 Aug 2022 12:36:35 +0000 (14:36 +0200)
committerTCY16 <tom@nlnetlabs.nl>
Mon, 15 Aug 2022 12:36:35 +0000 (14:36 +0200)
sldns/str2wire.c
sldns/str2wire.h
sldns/wire2str.c

index 303d49ba6689b59e14861cefbac99320cefd4a6d..a620738c2183c25d12125b18b6f81abbdf90dadf 100644 (file)
@@ -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)
index baee4236fe556896f6c03a4c604f953342f53598..18cfc4fa7f8877deae62d5ae07a29a39d4d55151 100644 (file)
@@ -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.
index 74d1b62dfe8d626abf7bb9e12c66032203c13311..5740aee770f33de2ba78fcc92f6a25330a0d263f 100644 (file)
@@ -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, "=\"");