FR-GV-202 - check for "too long" attributes, too
authorAlan T. DeKok <aland@freeradius.org>
Mon, 3 Jul 2017 16:34:00 +0000 (12:34 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 17 Jul 2017 12:22:12 +0000 (08:22 -0400)
src/lib/dhcp.c
src/lib/radius.c

index 0406480..d7bba42 100644 (file)
@@ -494,19 +494,17 @@ static int decode_tlv(VALUE_PAIR *tlv, const uint8_t *data, size_t data_len)
        if (head) {
                memcpy(tlv, head, sizeof(*tlv));
                head->next = NULL;
+               if (head->type == PW_TYPE_TLV) head->vp_tlv = NULL;
                pairfree(&head);
        }
 
        return 0;
 
 make_tlv:
-       tlv->vp_tlv = malloc(data_len);
-       if (!tlv->vp_tlv) {
-               fr_strerror_printf("No memory");
-               return -1;
-       }
-       memcpy(tlv->vp_tlv, data, data_len);
+       if (data_len > sizeof(tlv->vp_octets)) data_len = sizeof(tlv->vp_octets);
+       memcpy(tlv->vp_octets, data, data_len);
        tlv->length = data_len;
+       tlv->type = PW_TYPE_OCTETS;
 
        return 0;
 }
index 1c6be59..ade05c5 100644 (file)
@@ -2552,8 +2552,10 @@ static uint8_t *rad_coalesce(unsigned int attribute, size_t length,
        uint8_t *ptr, *tlv, *tlv_data;
 
        for (ptr = data + length;
-            ptr != (data + packet_length);
+            ptr < (data + packet_length);
             ptr += ptr[1]) {
+               if ((ptr + 2) > (data + length)) return NULL;
+
                if ((ptr[0] != PW_VENDOR_SPECIFIC) ||
                    (ptr[1] < (2 + 4 + 3)) || /* WiMAX VSA with continuation */
                    (ptr[2] != 0) || (ptr[3] != 0)) { /* our requirement */
@@ -2570,7 +2572,14 @@ static uint8_t *rad_coalesce(unsigned int attribute, size_t length,
                 *      If the vendor-length is too small, it's badly
                 *      formed, so we stop.
                 */
-               if ((ptr[2 + 4 + 1]) < 3) break;
+               if ((ptr[2 + 4 + 1]) < 3) return NULL;
+
+               /*
+                *      If it overflows the packet, it's bad.
+                */
+               if ((ptr + ptr[2 + 4 + 1]) > (data + packet_length)) {
+                       return NULL;
+               }
 
                tlv_length += ptr[2 + 4 + 1] - 3;
                if ((ptr[2 + 4 + 1 + 1] & 0x80) == 0) break;
@@ -2587,7 +2596,7 @@ static uint8_t *rad_coalesce(unsigned int attribute, size_t length,
         *      our newly created memory.
         */
        for (ptr = data + length;
-            ptr != (data + packet_length);
+            ptr < (data + packet_length);
             ptr += ptr[1]) {
                int this_length;