]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow for truncation of output buffers
authorAlan T. DeKok <aland@freeradius.org>
Wed, 22 Apr 2020 15:54:48 +0000 (11:54 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 22 Apr 2020 15:54:48 +0000 (11:54 -0400)
and test for it

src/bin/unit_test_attribute.c
src/tests/unit/protocols/radius/truncate.txt [new file with mode: 0644]

index 8e33b195dd9cd8b7c7317e1d21391eaf7b41ddda..b295768371d3d185b938030cf0ea2f534ee2e16f 100644 (file)
@@ -221,6 +221,7 @@ static ssize_t xlat_test(UNUSED TALLOC_CTX *ctx, UNUSED char **out, UNUSED size_
 static char            proto_name_prev[128];
 static dl_t            *dl;
 static dl_loader_t     *dl_loader;
+static size_t          max_packet_size = 0;
 
 size_t process_line(command_result_t *result, command_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen);
 static int process_file(bool *exit_now, TALLOC_CTX *ctx,
@@ -1478,7 +1479,7 @@ static size_t command_encode_pair(command_result_t *result, command_ctx_t *cc,
        char            *p = in;
 
        uint8_t         encoded[(COMMAND_OUTPUT_MAX / 2) - 1];
-       uint8_t         *enc_p = encoded, *enc_end = enc_p + sizeof(encoded);
+       uint8_t         *enc_p = encoded, *enc_end;
        VALUE_PAIR      *head = NULL, *vp;
 
        slen = load_test_point_by_command((void **)&tp, p, "tp_encode_pair");
@@ -1501,6 +1502,11 @@ static size_t command_encode_pair(command_result_t *result, command_ctx_t *cc,
                RETURN_OK_WITH_ERROR();
        }
 
+       enc_end = enc_p + sizeof(encoded);
+       if (max_packet_size && (max_packet_size < sizeof(encoded))) {
+               enc_end = enc_p + max_packet_size;
+       }
+
        for (vp = fr_cursor_talloc_iter_init(&cursor, &head, tp->next_encodable ? tp->next_encodable : fr_proto_next_encodable,
                                             cc->active_dict ? cc->active_dict : cc->config->dict, VALUE_PAIR);
             vp;
@@ -1563,8 +1569,9 @@ static size_t command_encode_proto(command_result_t *result, command_ctx_t *cc,
        ssize_t         slen;
        char            *p = in;
 
-       uint8_t         encoded[(COMMAND_OUTPUT_MAX / 2) - 1];
        VALUE_PAIR      *head = NULL;
+       size_t          encoded_len;
+       uint8_t         encoded[(COMMAND_OUTPUT_MAX / 2) - 1];
 
        slen = load_test_point_by_command((void **)&tp, p, "tp_encode_proto");
        if (!tp) {
@@ -1586,7 +1593,15 @@ static size_t command_encode_proto(command_result_t *result, command_ctx_t *cc,
                RETURN_OK_WITH_ERROR();
        }
 
-       slen = tp->func(cc->tmp_ctx, head, encoded, sizeof(encoded), encoder_ctx);
+       /*
+        *      Artificially limit the maximum packet size.
+        */
+       encoded_len = sizeof(encoded);
+       if (max_packet_size && (max_packet_size < encoded_len)) {
+               encoded_len = max_packet_size;
+       }
+
+       slen = tp->func(cc->tmp_ctx, head, encoded, encoded_len, encoder_ctx);
        fr_pair_list_free(&head);
        cc->last_ret = slen;
        if (slen < 0) {
@@ -1675,6 +1690,25 @@ static size_t command_match_regex(command_result_t *result, command_ctx_t *cc,
        }
 }
 
+/** Artificially limit the maximum packet size.
+ *
+ */
+static size_t command_max_packet_size(command_result_t *result, UNUSED command_ctx_t *cc,
+                                     char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
+{
+       unsigned long size;
+       char *end;
+
+       size = strtoul(in, &end, 10);
+       if ((size == ULONG_MAX) || *end || (size >= 65536)) {
+               fr_strerror_printf_push("Invalid integer");
+               RETURN_COMMAND_ERROR();
+       }
+
+       max_packet_size = size;
+       RETURN_OK(snprintf(data, COMMAND_OUTPUT_MAX, "%ld", max_packet_size));
+}
+
 /** Skip the test file if we're missing a particular feature
  *
  */
@@ -2121,6 +2155,11 @@ static fr_table_ptr_sorted_t     commands[] = {
                                        .usage = "match-regex <regex>",
                                        .description = "Compare the contents of the data buffer with a regular expression"
                                }},
+       { "max_packet_size",    &(command_entry_t){
+                                       .func = command_max_packet_size,
+                                       .usage = "max_packet_size <intger>",
+                                       .description = "Limit the maximum packet size for encode-proto"
+                               }},
        { "need-feature ",      &(command_entry_t){
                                        .func = command_need_feature,
                                        .usage = "need-feature <feature>",
diff --git a/src/tests/unit/protocols/radius/truncate.txt b/src/tests/unit/protocols/radius/truncate.txt
new file mode 100644 (file)
index 0000000..9296ee9
--- /dev/null
@@ -0,0 +1,23 @@
+#
+#  Correctly truncate encoded attributes / packets
+#
+proto radius
+proto-dictionary radius
+
+max_packet_size 32
+match 32
+
+encode-pair User-Name = "0123456789a123456789b123456789c123456789d123456789e123456789f"
+match 01 20 30 31 32 33 34 35 36 37 38 39 61 31 32 33 34 35 36 37 38 39 62 31 32 33 34 35 36 37 38 39
+
+decode-pair -
+match User-Name = "0123456789a123456789b123456789"
+
+encode-pair User-Password = "0123456789a123456789b123456789c123456789d123456789e123456789f"
+match 02 20 a6 df 3b f9 40 c8 4c 2d 28 7f 66 15 32 27 b6 be dc 8f f1 2a 7f cc b6 58 f9 d1 08 64 6b d2
+
+decode-pair - 
+match User-Password = "0123456789a123456789b123456789"
+
+count
+match 12