]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
check for overflow before decoding anything
authorAlan T. DeKok <aland@freeradius.org>
Wed, 6 Oct 2021 20:47:21 +0000 (16:47 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 6 Oct 2021 20:47:21 +0000 (16:47 -0400)
src/protocols/tacacs/decode.c

index 26488c53275528689a80528743ecca7b3c9bb4d4..4d0c4997c3b3ecbc086807dceda3afb5697a26d3 100644 (file)
@@ -91,7 +91,21 @@ static int tacacs_decode_args(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_att
        }
 
        /*
-        *      Then, do the dirty job...
+        *      Check for malformed packets before anything else.
+        */
+       for (i = 0; i < arg_cnt; i++) {
+               if ((p + arg_list[i]) > end) {
+                       fr_strerror_printf("'%s' argument %u length %u overflows the remaining data (%zu) in the packet",
+                                          parent->name, i, arg_list[i], end - p);
+                       return -1;
+               }
+
+               p += arg_list[i];
+       }
+       p = *data;
+
+       /*
+        *      Then, do the dirty job of creating attributes.
         */
        for (i = 0; i < arg_cnt; i++) {
                uint8_t const *value, *name_end, *arg_end;
@@ -100,12 +114,6 @@ static int tacacs_decode_args(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_att
 
                if (arg_list[i] < 2) goto next; /* skip malformed */
 
-               if (p + arg_list[i] > end) {
-                       fr_strerror_printf("'%s' argument %u length %u overflows the remaining data in the packet",
-                                          parent->name, i, arg_list[i]);
-                       return -1;
-               }
-
                memcpy(buffer, p, arg_list[i]);
                buffer[arg_list[i]] = '\0';
 
@@ -186,8 +194,8 @@ static int tacacs_decode_field(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_at
        fr_pair_t *vp;
 
        if ((p + field_len) > end) {
-               fr_strerror_printf("'%s' length %u overflows the remaining data in the packet",
-                                  da->name, field_len);
+               fr_strerror_printf("'%s' length %u overflows the remaining data (%zu) in the packet",
+                                  da->name, field_len, p - end);
                return -1;
        }