Skip to content

Commit

Permalink
allow for uncompressed labels, and add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alandekok committed Oct 21, 2019
1 parent 2ee8bb0 commit 9f98783
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/bin/unit_test_attribute.c
Expand Up @@ -1275,7 +1275,7 @@ static size_t command_encode_dns_label(command_result_t *result, UNUSED command_
RETURN_OK_WITH_ERROR();
}

ret = fr_value_box_to_dns_label(&need, dns_label, sizeof(dns_label), where, box);
ret = fr_value_box_to_dns_label(&need, dns_label, sizeof(dns_label), where, true, box);
talloc_free(box);

if (ret < 0) RETURN_OK_WITH_ERROR();
Expand Down
27 changes: 18 additions & 9 deletions src/lib/util/value.c
Expand Up @@ -1424,33 +1424,42 @@ static bool dns_label_compress(uint8_t const *start, uint8_t const *end, uint8_t
* @param[out] buf Buffer where labels are stored
* @param[in] buf_len The length of the output buffer
* @param[out] where Where to write this label
* @param[in] compression Whether or not to do DNS label compression.
* @param[in] value to encode.
* @return
* - 0 no bytes were written, see need value to determine if it was because
* the fr_value_box_t was #FR_TYPE_OCTETS/#FR_TYPE_STRING and was
* NULL (which is unfortunately valid)
* - 0 no bytes were written, see need value to determine
* - >0 the number of bytes written to "where", NOT "buf + where + outlen"
* - <0 on error.
*/
ssize_t fr_value_box_to_dns_label(size_t *need, uint8_t *buf, size_t buf_len, uint8_t *where, fr_value_box_t const *value)
ssize_t fr_value_box_to_dns_label(size_t *need, uint8_t *buf, size_t buf_len, uint8_t *where, bool compression,
fr_value_box_t const *value)
{
uint8_t *label;
uint8_t *end = buf + buf_len;
uint8_t const *q, *strend;
uint8_t *data;
int namelen = 0;

if (!buf || !buf_len || !where || !value) return -1;
if (!buf || !buf_len || !where || !value) {
fr_strerror_printf("Invalid input");
return -1;
}

/*
* Don't allow stupidities
*/
if (!((where >= buf) && (where < (buf + buf_len)))) return -1;
if (!((where >= buf) && (where < (buf + buf_len)))) {
fr_strerror_printf("Label is outside of buffer");
return -1;
}

/*
* We can only encode strings.
*/
if (value->type != FR_TYPE_STRING) return -1;
if (value->type != FR_TYPE_STRING) {
fr_strerror_printf("Asked to encode non-string type");
return -1;
}

if (value->vb_length > 255) {
fr_strerror_printf("Label is too long");
Expand Down Expand Up @@ -1546,7 +1555,7 @@ ssize_t fr_value_box_to_dns_label(size_t *need, uint8_t *buf, size_t buf_len, ui
}

/*
* Allow [-0-9a-zA-Z]
* Only encode [-0-9a-zA-Z]. Anything else is forbidden.
*/
if (!((*q == '-') || ((*q >= '0') && (*q <= '9')) ||
((*q >= 'A') && (*q <= 'Z')) || ((*q >= 'a') && (*q <= 'z')))) {
Expand All @@ -1565,7 +1574,7 @@ ssize_t fr_value_box_to_dns_label(size_t *need, uint8_t *buf, size_t buf_len, ui
* Only one label, don't compress it. Or, the label is
* already compressed.
*/
if ((buf == where) || ((data - where) <= 2)) goto done;
if (!compression || (buf == where) || ((data - where) <= 2)) goto done;

/*
* Do label compression on the resulting string, starting
Expand Down
2 changes: 1 addition & 1 deletion src/lib/util/value.h
Expand Up @@ -510,7 +510,7 @@ ssize_t fr_value_box_from_network(TALLOC_CTX *ctx,
fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv,
uint8_t const *src, size_t len, bool tainted);

ssize_t fr_value_box_to_dns_label(size_t *need, uint8_t *buf, size_t buflen, uint8_t *where, fr_value_box_t const *value);
ssize_t fr_value_box_to_dns_label(size_t *need, uint8_t *buf, size_t buflen, uint8_t *where, bool compression, fr_value_box_t const *value);

ssize_t fr_dns_label_length(uint8_t const *buf, size_t buf_len, uint8_t const **p_label);

Expand Down
15 changes: 10 additions & 5 deletions src/protocols/dhcpv6/encode.c
Expand Up @@ -264,10 +264,13 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
*/
case FR_TYPE_STRING:
/*
* DNS labels get a special encoder.
* DNS labels get a special encoder. Since we're
* only encoding one value, it's always
* uncompressed.
*/
if (da->flags.subtype == FLAG_ENCODE_DNS_LABEL) {
slen = fr_value_box_to_dns_label(NULL, p, outlen, p, &vp->data);
if ((da->flags.subtype == FLAG_ENCODE_DNS_LABEL) ||
(da->flags.subtype == FLAG_ENCODE_UNCOMPRESSED_DNS_LABEL)) {
slen = fr_value_box_to_dns_label(NULL, p, outlen, p, false, &vp->data);

/*
* @todo - check for free space, etc.
Expand Down Expand Up @@ -492,14 +495,16 @@ static inline ssize_t encode_array(uint8_t *out, size_t outlen,
* DNS labels have internalized length, so we don't need
* length headers.
*/
if ((da->type == FR_TYPE_STRING) && (da->flags.subtype == FLAG_ENCODE_DNS_LABEL)) {
if ((da->type == FR_TYPE_STRING) && da->flags.subtype){
bool compression = (da->flags.subtype == FLAG_ENCODE_DNS_LABEL);

while (p < end) {
vp = fr_cursor_current(cursor);

/*
* @todo - encode length and stuff
*/
slen = fr_value_box_to_dns_label(NULL, out, outlen, p, &vp->data);
slen = fr_value_box_to_dns_label(NULL, out, outlen, p, compression, &vp->data);
if (slen <= 0) return PAIR_ENCODE_ERROR;

p += slen;
Expand Down
2 changes: 1 addition & 1 deletion src/tests/unit/data_types.txt
Expand Up @@ -93,7 +93,7 @@ match Aug 21 2019 07:43:03 UTC
#data foo

#
# DNS labels WITHOUT compression
# DNS labels
#
encode-dns-label foo.com
match 03 66 6f 6f 03 63 6f 6d 00
Expand Down
17 changes: 16 additions & 1 deletion src/tests/unit/dhcpv6.txt
Expand Up @@ -182,5 +182,20 @@ match 00 15 00 15 03 66 6f 6f 02 63 61 00 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
encode-pair SIP-Server-Domain-Name-List = "www.example.com", SIP-Server-Domain-Name-List = "ftp.example.com"
match 00 15 00 17 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 03 66 74 70 c0 04

encode-pair SIP-Server-Domain-Name-List = "www.example.com", SIP-Server-Domain-Name-List = "ftp.example.com", SIP-Server-Domain-Name-List = "ns.example.com"
match 00 15 00 1c 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 03 66 74 70 c0 04 02 6e 73 c0 04

#
# This attribute is NOT compressed!
#
encode-pair BCMCS-Server-Domain-Name-List = "www.example.com"
match 00 21 00 11 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00

encode-pair BCMCS-Server-Domain-Name-List = "www.example.com", BCMCS-Server-Domain-Name-List = "ftp.example.com"
match 00 21 00 22 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 03 66 74 70 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00

encode-pair BCMCS-Server-Domain-Name-List = "www.example.com", BCMCS-Server-Domain-Name-List = "ftp.example.com", BCMCS-Server-Domain-Name-List = "ns.example.com"
match 00 21 00 32 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 03 66 74 70 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 02 6e 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00

count
match 82
match 90

0 comments on commit 9f98783

Please sign in to comment.