]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
add escaping
authorTom Carpay <tom@nlnetlabs.nl>
Thu, 27 May 2021 13:22:32 +0000 (15:22 +0200)
committerTom Carpay <tom@nlnetlabs.nl>
Thu, 27 May 2021 13:22:32 +0000 (15:22 +0200)
sldns/str2wire.c
sldns/wire2str.c

index aec8e51fe3408031d7beb3a09ce98499b9039959..83eca3524325d40055696efcb4730b0a0da9c88d 100644 (file)
@@ -711,6 +711,18 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
        /* write rdata length */
        sldns_write_uint16(rr+dname_len+8, (uint16_t)(rr_cur_len-dname_len-10));
        *rr_len = rr_cur_len;
+       /* SVCB/HTTPS handling  */
+       if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) {
+
+               
+
+               // 1. Find the size
+               // 2. qsort the data according to the keys
+               // 3. verify that keys are unique
+               // 4. verify that mandatory keys are present and unique
+
+
+       }
        return LDNS_WIREPARSE_ERR_OK;
 }
 
@@ -976,14 +988,17 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len)
                if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1))
                        return SVCB_KEY_IPV6HINT;
                break;
+
        case sizeof("ech")-1:
                if (!strncmp(key, "ech", sizeof("ech")-1))
                        return SVCB_KEY_ECH;
                break;
+
        default:
                break;
        }
-               if (key_len > sizeof(buf) - 1) {}
+       
+       if (key_len > sizeof(buf) - 1) {}
                // ERROR: Unknown SvcParamKey
        else {
                memcpy(buf, key, key_len);
@@ -1286,7 +1301,6 @@ int sldns_str2wire_svcbparam_alpn_value(const char* val,
        size_t      str_len;
        size_t      dst_len;
        size_t          val_len;
-       int wire_len;
        
        val_len = strlen(val);
 
@@ -1328,8 +1342,28 @@ static int
 sldns_str2wire_svcparam_key_value(const char *key, size_t key_len,
        const char *val, uint8_t* rd, size_t* rd_len)
 {
+       size_t str_len;
        uint16_t svcparamkey = sldns_str2wire_svcparam_key_lookup(key, key_len);
 
+
+       // @TODO add case where svcparamkey == -1
+
+       /* key and no value case*/
+       if (val == NULL) {
+               sldns_write_uint16(rd, svcparamkey);
+               sldns_write_uint16(rd + 2, 0);
+               *rd_len = 4;
+
+               return LDNS_WIREPARSE_ERR_OK;
+       }
+
+       // @TODO unescape characters in the value list
+
+       // if (val[0] == '"' && val[str_len - 1]) {
+
+       // }
+
+       /* value is non-empty */
        switch (svcparamkey) {
        case SVCB_KEY_PORT:
                return sldns_str2wire_svcparam_port(val, rd, rd_len);
@@ -1340,18 +1374,24 @@ sldns_str2wire_svcparam_key_value(const char *key, size_t key_len,
        case SVCB_KEY_MANDATORY:
                return sldns_str2wire_svcbparam_mandatory(val, rd, rd_len);
        case SVCB_KEY_NO_DEFAULT_ALPN:
+
+               // @TODO is this superfluous now?
+
                return sldns_str2wire_svcbparam_no_default_alpn(val, rd, rd_len);
-               // if(zone_is_slave(parser->current_zone->opts))
-               //      zc_warning_prev_line("no-default-alpn should not have a value");
-               // else
-               //      zc_error_prev_line("no-default-alpn should not have a value");
-               // break;
        case SVCB_KEY_ECH:
                return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len);
        case SVCB_KEY_ALPN:
                return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len);
        default:
-               break;
+               // @TODO escaping here -> copy from alpn?
+
+               str_len = strlen(val);
+               sldns_write_uint16(rd, svcparamkey);
+               sldns_write_uint16(rd + 2, str_len);
+               memcpy(rd + 4, val, str_len);
+               *rd_len = 4 + str_len;
+
+               return LDNS_WIREPARSE_ERR_OK;
        }
 
        // @TODO change to error?
@@ -1360,18 +1400,35 @@ sldns_str2wire_svcparam_key_value(const char *key, size_t key_len,
 
 int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len)
 {
+       size_t str_len;
        const char* eq_pos;
-
-       int ret;
+       char unescaped_val[65536];
+       char* val_out = unescaped_val;
+       const char* val_in;
 
        eq_pos = strchr(str, '=');
 
-       // @TODO handle "key=" case
+       if (eq_pos != NULL && eq_pos[1]) { /* case: key=value */
+               val_in = eq_pos + 1;
+               
+               /* unescape characters and "" blocks */
+               if (*val_in == '"') {
+                       val_in++;
+                       while (*val_in != '"' && sldns_parse_char( (uint8_t*) val_out, &val_in)) {
+                               val_out++;
+                       }
+               } else {
+                       while ( sldns_parse_char( (uint8_t*) val_out, &val_in)) {
+                               val_out++;
+                       }
+               }
+               *val_out = 0;
 
-       /* Verify that we have a have a value */
-       if (eq_pos != NULL) {
-               return sldns_str2wire_svcparam_key_value(str, eq_pos - str, eq_pos + 1, rd, rd_len);
-       } else {
+               return sldns_str2wire_svcparam_key_value(str, eq_pos - str, 
+                                                        unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
+       } else if (eq_pos != NULL && !(eq_pos[1])) { /* case: key= */
+               return sldns_str2wire_svcparam_key_value(str, eq_pos - str, NULL, rd, rd_len);
+       } else { /* case: key */
                return sldns_str2wire_svcparam_key_value(str, strlen(str), NULL, rd, rd_len);
        }
 
index 07a4911c4a26df6bb85b83188e0abf47de033ada..cf87f0aa8067c83a12996267f2cd69fe0fefb4bb 100644 (file)
@@ -199,7 +199,7 @@ sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
 /* draft-ietf-dnsop-svcb-https-04: 6. Initial SvcParamKeys */
 const char *svcparamkey_strs[] = {
        "mandatory", "alpn", "no-default-alpn", "port",
-       "ipv4hint", "echconfig", "ipv6hint"
+       "ipv4hint", "ech", "ipv6hint"
 };
 
 char* sldns_wire2str_pkt(uint8_t* data, size_t len)
@@ -965,6 +965,8 @@ static int sldns_wire2str_svcparam_port2str(char** s,
        if (data_len != 2)
                return -1; /* wireformat error, a short is 2 bytes */
        w = sldns_str_print(s, slen, "=%d", (int)sldns_read_uint16(data));
+       *data     += 2;
+
        return w;
 }
 
@@ -1117,9 +1119,10 @@ static int sldns_wire2str_svcparam_ech2str(char** s,
 
 int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
 {
+       char ch;
        uint16_t svcparamkey, data_len;
        int written_chars = 0;
-       int r;
+       int r, i;
 
        /* verify that we have enough data to read svcparamkey and data_len */
        if(*dlen < 4)
@@ -1130,12 +1133,15 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
        *d    += 4;
        *dlen -= 4;
 
+       // fprintf(stderr, "data_len: %hu\n", data_len);
+
        /* verify that we have data_len data */
        if (data_len > *dlen)
                return -1; 
 
        written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
        if (!data_len) {
+
                /* Some SvcParams MUST have values */
                switch (svcparamkey) {
                case SVCB_KEY_ALPN:
@@ -1143,11 +1149,12 @@ 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:
-                       return -1;
+                       return LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE;
                default:
-                       return written_chars;
+                       return LDNS_WIREPARSE_ERR_OK;
                }
        }
+
        switch (svcparamkey) {
        case SVCB_KEY_PORT:
                r = sldns_wire2str_svcparam_port2str(s, slen, data_len, *d);
@@ -1170,6 +1177,22 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
                r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
                break;
        default:
+               r += sldns_str_print(s, slen, "=\"");
+
+               for (i = 0; i < data_len; i++) {
+                       ch = (*d)[i];
+
+                       if (ch == '"' || ch == '\\')
+                               r += sldns_str_print(s, slen, "\\%c", ch);
+
+                       else if (!isprint(ch))
+                               r += sldns_str_print(s, slen, "\\%03u", (unsigned) ch);
+
+                       else
+                               r += sldns_str_print(s, slen, "%c", ch);
+
+               }
+               r += sldns_str_print(s, slen, "%c", '"');
                break;
        }
        if (r <= 0)