]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow for uncompressed labels, and add unit tests
authorAlan T. DeKok <aland@freeradius.org>
Mon, 21 Oct 2019 16:42:13 +0000 (12:42 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 21 Oct 2019 16:42:31 +0000 (12:42 -0400)
src/bin/unit_test_attribute.c
src/lib/util/value.c
src/lib/util/value.h
src/protocols/dhcpv6/encode.c
src/tests/unit/data_types.txt
src/tests/unit/dhcpv6.txt

index 1b5358ebf86d802e9c804275c41ded822e8ef191..f677cc2898c02a6e3a55daf8962de705e4875b65 100644 (file)
@@ -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();
index a9b05b5a64cf3b5e3424c4e56a4fbfb6feb8b1ed..748ec6b7ad23ec64e7b8a0e45d0f67bf0775a4ec 100644 (file)
@@ -1424,15 +1424,15 @@ 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;
@@ -1440,17 +1440,26 @@ ssize_t fr_value_box_to_dns_label(size_t *need, uint8_t *buf, size_t buf_len, ui
        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");
@@ -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')))) {
@@ -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
index fc5d76a6a240bb8fa5d53097243097c348242082..0304ebef6d9a110e07e1c203107bbb294b4fe477 100644 (file)
@@ -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);
 
index f34d2b034c26923c145da0fedac5e6d441611d1e..bebd2f1496dc3719b06c5a6a9d2b71bf80b18f89 100644 (file)
@@ -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.
@@ -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;
index bac66df0d705135a62846c7b38fcea48840c09c2..5fafc55353dc7a0c9619c8b4834dab28abef3c86 100644 (file)
@@ -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
index e4d2af7037bc8d50a4238b6ab0671802d89bb032..7532f0f6b03d2af6aad313ea03e6ea14a4f76fb4 100644 (file)
@@ -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