]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add marker array for tracking where labels can point to
authorAlan T. DeKok <aland@freeradius.org>
Tue, 12 Oct 2021 19:52:27 +0000 (15:52 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 12 Oct 2021 19:52:27 +0000 (15:52 -0400)
src/lib/util/dns.c
src/lib/util/dns.h
src/protocols/dns/decode.c

index f3b836627aed3f6fc4b9de6b60685f5ef2296aef..b6e487a7a6cbd3975b646ab579e24668351d27a7 100644 (file)
@@ -113,12 +113,25 @@ static int dns_label_add(fr_dns_labels_t *lb, uint8_t const *start, uint8_t cons
        return 0;
 }
 
+static void dns_label_mark(fr_dns_labels_t *lb, uint8_t const *p)
+{
+       if (!lb || !lb->mark) return;
+
+       fr_assert(p >= (lb->start + 12)); /* can't point to the packet header */
+       fr_assert(!lb->end || (p < lb->end));
+
+       lb->mark[p - lb->start] = 1;
+}
+
+
 static bool dns_pointer_valid(fr_dns_labels_t *lb, uint16_t offset)
 {
        int i;
 
        if (!lb) return true;   /* we have no idea, so allow it */
 
+       if (lb->mark) return (lb->mark[offset] != 0);
+
        for (i = 0; i < lb->num; i++) {
                FR_PROTO_TRACE("Checking block %d %u..%u against %u",
                               i, lb->blocks[i].start, lb->blocks[i].end, offset);
@@ -1063,6 +1076,8 @@ ssize_t fr_dns_label_uncompressed_length(uint8_t const *packet, uint8_t const *b
                 */
                if ((p + *p + 1) > end) goto overflow;
 
+               dns_label_mark(lb, p);
+
                /*
                 *      Account for the '.' on every label after the
                 *      first one.
index 31be362fbc89ea43ea323e0b6d891a2946a8c5a2..f639c156f2e2d2dae6cafaa8fed955fd699f1980 100644 (file)
@@ -34,6 +34,8 @@ typedef struct {
 
 typedef struct {
        uint8_t const   *start;         //!< start of packet
+       uint8_t const   *end;           //!< end of the packet
+       uint8_t         *mark;          //!< markup buffer
        int             num;            //!< number of used labels
        int             max;            //! maximum number of labels
        fr_dns_block_t  blocks[];       //!< array holding "max" labels
index fcbd4a3b890744ba7d774912242e897bee92a7e6..6ec8c9a0280108ac302ebb643ae705dd46faede2 100644 (file)
@@ -696,9 +696,14 @@ static ssize_t fr_dns_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t
                lb->blocks[0].start = 12;
                lb->blocks[0].end = 12;
                lb->num = 1;
+
+               memset(packet_ctx->lb->mark, 0, talloc_array_length(packet_ctx->lb->mark));
        } else {
                packet_ctx->lb = fr_dns_labels_init(packet_ctx, data, 256);
                fr_assert(packet_ctx->lb != NULL);
+
+               packet_ctx->lb->end = data + data_len;
+               packet_ctx->lb->mark = talloc_zero_array(packet_ctx->lb, uint8_t, 65535);
        }
 
        return fr_dns_decode(ctx, out, data, data_len,  packet_ctx);