add escaping

This commit is contained in:
Tom Carpay 2021-05-27 15:22:32 +02:00
parent 21413aed78
commit eb0e029dda
2 changed files with 99 additions and 19 deletions

View 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);
}

View 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)