From: Alan T. DeKok Date: Sun, 12 Sep 2021 19:54:22 +0000 (-0400) Subject: allow underscores as the first character of a label X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f641572449e0bf356c9984ec9c42d948bf5e189d;p=thirdparty%2Ffreeradius-server.git allow underscores as the first character of a label --- diff --git a/src/lib/util/dns.c b/src/lib/util/dns.c index 2d5e7a7af69..1ffdf35a72a 100644 --- a/src/lib/util/dns.c +++ b/src/lib/util/dns.c @@ -48,9 +48,6 @@ static bool labelcmp(uint8_t const *a, uint8_t const *b, size_t len) * If one or the other isn't a letter, we can't * do case insensitive comparisons of them, so * they can't match. - * - * @todo - allow for '_' at the beginning of a - * label. */ if (!(((*a >= 'a') && (*a <= 'z')) || ((*a >= 'A') && (*a <= 'Z')))) return false; if (!(((*b >= 'a') && (*b <= 'z')) || ((*b >= 'A') && (*b <= 'Z')))) return false; @@ -536,6 +533,7 @@ ssize_t fr_dns_label_from_value_box(size_t *need, uint8_t *buf, size_t buf_len, uint8_t const *end = buf + buf_len; uint8_t const *q, *strend, *last; uint8_t *data; + bool underscore = true; if (!buf || !buf_len || !where || !value) { fr_strerror_const("Invalid input"); @@ -588,10 +586,18 @@ ssize_t fr_dns_label_from_value_box(size_t *need, uint8_t *buf, size_t buf_len, } /* - * @todo - allow for '_' at the beginning of a - * label. + * Convert it piece by piece. */ while (q < strend) { + /* + * Allow underscore at the start of a label. + */ + if (underscore) { + underscore = false; + + if (*q == '_') goto next; + } + if (*q == '.') { /* * Don't count final dot as an @@ -609,12 +615,19 @@ ssize_t fr_dns_label_from_value_box(size_t *need, uint8_t *buf, size_t buf_len, } last = q; + /* + * We had a dot, allow underscore as the + * first character of the next label. + */ + underscore = true; + } else if (!((*q == '-') || ((*q >= '0') && (*q <= '9')) || ((*q >= 'A') && (*q <= 'Z')) || ((*q >= 'a') && (*q <= 'z')))) { - fr_strerror_printf("Invalid character %02x in label", *q); + fr_strerror_printf("Invalid character 0x%02x in label", *q); return -1; } + next: q++; if ((q - last) > 63) { @@ -708,7 +721,7 @@ done: */ ssize_t fr_dns_label_uncompressed_length(uint8_t const *buf, size_t buf_len, uint8_t const **next) { - uint8_t const *p, *q, *end; + uint8_t const *p, *q, *end, *label_end; uint8_t const *current, *start; size_t length; bool at_first_label, already_set_next; @@ -882,19 +895,26 @@ ssize_t fr_dns_label_uncompressed_length(uint8_t const *buf, size_t buf_len, uin return -(p - buf); } + q = p + 1; + label_end = q + *p; + + /* + * Allow for underscore at the beginning of a + * label. + */ + if (*q == '_') q++; + /* * Verify that the contents of the label are OK. */ - for (q = p + 1; q < p + *p + 1; q++) { - /* - * @todo - allow for '_' at the beginning of a - * label. - */ + while (q < label_end) { if (!((*q == '-') || ((*q >= '0') && (*q <= '9')) || ((*q >= 'A') && (*q <= 'Z')) || ((*q >= 'a') && (*q <= 'z')))) { - fr_strerror_printf("Invalid character %02x in label", *q); + fr_strerror_printf("Invalid character 0x%02x in label", *q); return -(q - buf); } + + q++; } p += *p + 1; diff --git a/src/tests/unit/data_types.txt b/src/tests/unit/data_types.txt index 857764e3ec3..640debb296d 100644 --- a/src/tests/unit/data_types.txt +++ b/src/tests/unit/data_types.txt @@ -181,6 +181,15 @@ match 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 03 66 74 70 c0 04 03 77 decode-dns-label - match www.example.com,ftp.example.com,www.example.org,ftp.example.org,ns.example.org +# +# Underscores are allowed as the first character of a label. +# +encode-dns-label _foo.com +match 04 5f 66 6f 6f 03 63 6f 6d 00 + +decode-dns-label - +match _foo.com + # # Error cases # @@ -201,6 +210,9 @@ match Empty labels are invalid encode-dns-label www..foo.com match Double dots '..' are forbidden +# underscore as non-first character is illegal +encode-dns-label www_foo.com +match Invalid character 0x5f in label count -match 98 +match 104