static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len)
{
size_t nparams = 0, i, j;
- uint8_t new_rdata[65536];
+ uint8_t new_rdata[LDNS_MAX_RDFLEN];
uint8_t* new_rdata_ptr = new_rdata;
uint8_t* svcparams[64];
uint8_t* mandatory = NULL;
rdata_ptr += svcbparam_len;
nparams += 1;
- if (nparams > sizeof(svcparams)/8)
+ if (nparams > MAX_NUMBER_OF_SVCPARAMS)
return LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS;
}
if (mandatory) {
/* Divide by sizeof(uint16_t)*/
- uint16_t mandatory_len = sldns_read_uint16(mandatory + 2) >> 1;
+ uint16_t mandatory_len = sldns_read_uint16(mandatory + 2) / sizeof(uint16_t);
/* Guaranteed by sldns_str2wire_svcparam_key_value */
assert(mandatory_len > 0);
/* single 0 represents empty buffer */
if(strcmp(val, "0") == 0) {
+ if (*rd_len < 4)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL
sldns_write_uint16(rd, SVCB_KEY_ECH);
sldns_write_uint16(rd + 2, 0);
return NULL;
}
+/* The source is already properly unescaped, this double unescaping is purely to allow for
+ * comma's in comma seperated alpn lists.
+ */
static size_t
sldns_str2wire_svcbparam_parse_copy_unescaped(uint8_t *dst,
const char *src, size_t len)
sldns_str2wire_svcbparam_alpn_value(const char* val,
uint8_t* rd, size_t* rd_len)
{
- uint8_t unescaped_dst[65536];
+ uint8_t unescaped_dst[LDNS_MAX_RDFLEN];
uint8_t *dst = unescaped_dst;
const char *next_str;
size_t str_len;
size_t dst_len;
- size_t val_len;
+ size_t val_len;
val_len = strlen(val);
val = next_str + 1;
}
dst_len = dst - unescaped_dst;
-
+ if (*rd_len < 4 + dst_len)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
sldns_write_uint16(rd, SVCB_KEY_ALPN);
sldns_write_uint16(rd + 2, dst_len);
memcpy(rd + 4, unescaped_dst, dst_len);
case SVCB_KEY_IPV6HINT:
return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM;
default:
+ if (*rd_len < 4)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
sldns_write_uint16(rd, svcparamkey);
sldns_write_uint16(rd + 2, 0);
*rd_len = 4;
return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len);
default:
str_len = strlen(val);
+ if (*rd_len < 4 + str_len)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
sldns_write_uint16(rd, svcparamkey);
sldns_write_uint16(rd + 2, str_len);
memcpy(rd + 4, val, str_len);
int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len)
{
const char* eq_pos;
- char unescaped_val[65536];
+ char unescaped_val[LDNS_MAX_RDFLEN];
char* val_out = unescaped_val;
const char* val_in;
/* unescape characters and "" blocks */
if (*val_in == '"') {
val_in++;
- while (*val_in != '"' && sldns_parse_char( (uint8_t*) val_out, &val_in)) {
+ while (*val_in != '"'
+ && val_out - unescaped_val < sizeof(unescaped_val) - 1
+ && sldns_parse_char( (uint8_t*) val_out, &val_in)) {
val_out++;
}
} else {
- while ( sldns_parse_char( (uint8_t*) val_out, &val_in)) {
+ while (val_out - unescaped_val < sizeof(unescaped_val) - 1
+ && sldns_parse_char( (uint8_t*) val_out, &val_in)) {
val_out++;
}
}
else {
return sldns_str2wire_svcparam_value(str, strlen(str), NULL, rd, rd_len);
}
-
- return LDNS_WIREPARSE_ERR_OK;
}
int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
#define SVCB_KEY_NO_DEFAULT_ALPN 2
#define SVCB_KEY_PORT 3
#define SVCB_KEY_IPV4HINT 4
-#define SVCB_KEY_ECH 5
+#define SVCB_KEY_ECH 5
#define SVCB_KEY_IPV6HINT 6
#define SVCPARAMKEY_COUNT 7
if ((data_len % LDNS_IP4ADDRLEN) == 0) {
if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
- return 0; /* wireformat error, incorrect size or inet family */
+ return -1; /* wireformat error, incorrect size or inet family */
w += sldns_str_print(s, slen, "=%s", ip_str);
data += LDNS_IP4ADDRLEN;
while ((data_len -= LDNS_IP4ADDRLEN) > 0) {
if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
- return 0; /* wireformat error, incorrect size or inet family */
+ return -1; /* wireformat error, incorrect size or inet family */
w += sldns_str_print(s, slen, ",%s", ip_str);
data += LDNS_IP4ADDRLEN;
}
- }
+ } else
+ return -1;
return w;
}
if ((data_len % LDNS_IP6ADDRLEN) == 0) {
if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
- return 0; /* wireformat error, incorrect size or inet family */
+ return -1; /* wireformat error, incorrect size or inet family */
w += sldns_str_print(s, slen, "=%s", ip_str);
data += LDNS_IP6ADDRLEN;
while ((data_len -= LDNS_IP6ADDRLEN) > 0) {
if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
- return 0; /* wireformat error, incorrect size or inet family */
+ return -1; /* wireformat error, incorrect size or inet family */
w += sldns_str_print(s, slen, ",%s", ip_str);
data += LDNS_IP6ADDRLEN;
}
- }
+ } else
+ return -1;
return w;
}
assert(data_len > 0);
- // if (data_len % sizeof(uint16_t))
- // return 0; // wireformat error, data_len must be multiple of shorts
+ if (data_len % sizeof(uint16_t))
+ return -1; // wireformat error, data_len must be multiple of shorts
w += sldns_str_print(s, slen, "=");
w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
data += 2;
uint8_t *dp = (void *)data;
int w = 0;
- assert(data_len > 0); /* Guaranteed by rdata_svcparam_to_string */
+ assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */
w += sldns_str_print(s, slen, "=\"");
while (data_len) {
+ /* alpn is list of length byte (str_len) followed by a string of that size */
uint8_t i, str_len = *dp++;
if (str_len > --data_len)
- return 0;
+ return -1;
for (i = 0; i < str_len; i++) {
if (dp[i] == '"' || dp[i] == '\\')
int size;
int w = 0;
- assert(data_len > 0); /* Guaranteed by rdata_svcparam_to_string */
+ assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */
w += sldns_str_print(s, slen, "=\"");
- size = sldns_b64_ntop(data, data_len, *s, *slen);
+ if ((size = sldns_b64_ntop(data, data_len, *s, *slen)) < 0)
+ return -1;
(*s) += size;
(*slen) -= size;
w += sldns_str_print(s, slen, "\"");
- // @TODO fix check
- // if(size > *slen) {
- // buffer_skip(output, size);
- // }
-
return w + size;
}
case SVCB_KEY_IPV4HINT:
case SVCB_KEY_IPV6HINT:
case SVCB_KEY_MANDATORY:
- return LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE;
+ return -1;
default:
- return LDNS_WIREPARSE_ERR_OK;
+ return written_chars;
}
}
r += sldns_str_print(s, slen, "%c", ch);
}
- r += sldns_str_print(s, slen, "%c", '"');
+ r += sldns_str_print(s, slen, "\"");
break;
}
if (r <= 0)
/** tsig errors are the rcodes with extra (higher) values */
extern struct sldns_struct_lookup_table* sldns_tsig_errors;
-/* draft-ietf-dnsop-svcb-https-04: 6. Initial SvcParamKeys */
-extern const char *svcparamkey_strs[];
-
/**
* Convert wireformat packet to a string representation
* @param data: wireformat packet data (starting at ID bytes).
s = sldns_fp2wire_rr_buf(in, rr, &rr_len, &dname_len, &state);
if (s) {
- fprintf( stderr, "parse error %d:%d: %s"
+ fprintf( stderr, "parse error %d:%d: %s\n"
, state.lineno, LDNS_WIREPARSE_OFFSET(s)
, sldns_get_errorstr_parse(s));
break;
}
if (in)
fclose(in);
+ free(str);
return !in || s ? EXIT_FAILURE : EXIT_SUCCESS;
}