]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow encode/decode of response packets, too
authorAlan T. DeKok <aland@freeradius.org>
Sat, 10 Jan 2026 13:10:29 +0000 (08:10 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 10 Jan 2026 13:10:29 +0000 (08:10 -0500)
src/protocols/radius/attrs.h
src/protocols/radius/base.c
src/protocols/radius/encode.c
src/tests/unit/protocols/radius/packet_radius.txt
src/tests/unit/protocols/radius/rfc2868.txt

index 1cdf526e62bf22d5cd9d78e69fdb9ac0ab5ac4b3..5b5981c3b3c21edeed6fe86dec16ebaebdb5fc7b 100644 (file)
@@ -40,3 +40,5 @@ extern HIDDEN fr_dict_attr_t const *attr_message_authenticator;
 extern HIDDEN fr_dict_attr_t const *attr_state;
 extern HIDDEN fr_dict_attr_t const *attr_vendor_specific;
 extern HIDDEN fr_dict_attr_t const *attr_nas_filter_rule;
+
+extern HIDDEN const fr_radius_packet_code_t allowed_replies[FR_RADIUS_CODE_MAX];
index d6bce6afccf47f353caad012ddd56c86cf0300ed..2ebc2e2c5d2c6b070234b0cbbf86517e95d7a22b 100644 (file)
@@ -173,7 +173,7 @@ char const *fr_radius_packet_name[FR_RADIUS_CODE_MAX] = {
 /** If we get a reply, the request must come from one of a small
  * number of packet types.
  */
-static const fr_radius_packet_code_t allowed_replies[FR_RADIUS_CODE_MAX] = {
+const fr_radius_packet_code_t allowed_replies[FR_RADIUS_CODE_MAX] = {
        [FR_RADIUS_CODE_ACCESS_ACCEPT]          = FR_RADIUS_CODE_ACCESS_REQUEST,
        [FR_RADIUS_CODE_ACCESS_CHALLENGE]       = FR_RADIUS_CODE_ACCESS_REQUEST,
        [FR_RADIUS_CODE_ACCESS_REJECT]          = FR_RADIUS_CODE_ACCESS_REQUEST,
index 48c3b070daf7171bf67aa7c518e432c4adb0a3b3..6773ee45f06dea4f8815b3e8ada08d7712519463 100644 (file)
@@ -1757,9 +1757,17 @@ static ssize_t fr_radius_encode_proto(TALLOC_CTX *ctx, fr_pair_list_t *vps, uint
        int packet_type = FR_RADIUS_CODE_ACCESS_REQUEST;
        fr_pair_t *vp;
        ssize_t slen;
+       uint8_t const *request_authenticator = NULL;
 
        vp = fr_pair_find_by_da(vps, NULL, attr_packet_type);
-       if (vp) packet_type = vp->vp_uint32;
+       if (vp) {
+               packet_type = vp->vp_uint32;
+
+               if (!FR_RADIUS_PACKET_CODE_VALID(packet_type)) {
+                       fr_strerror_printf("Invalid packet code %u", packet_type);
+                       return -1;
+               }
+       }
 
        /*
         *      Force specific values for testing.
@@ -1767,18 +1775,14 @@ static ssize_t fr_radius_encode_proto(TALLOC_CTX *ctx, fr_pair_list_t *vps, uint
        if ((packet_type == FR_RADIUS_CODE_ACCESS_REQUEST) || (packet_type == FR_RADIUS_CODE_STATUS_SERVER)) {
                vp = fr_pair_find_by_da(vps, NULL, attr_packet_authentication_vector);
                if (!vp) {
-                       int i;
-                       uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH];
-
-                       for (i = 0; i < RADIUS_AUTH_VECTOR_LENGTH; i++) {
-                               data[4 + i] = fr_fast_rand(&packet_ctx->rand_ctx);
-                       }
-
-                       fr_pair_list_append_by_da_len(ctx, vp, vps, attr_packet_authentication_vector, vector, sizeof(vector), false);
+                       fr_pair_list_append_by_da_len(ctx, vp, vps, attr_packet_authentication_vector,
+                                                     packet_ctx->request_authenticator, RADIUS_AUTH_VECTOR_LENGTH, false);
                }
        }
 
        packet_ctx->code = packet_type;
+       packet_ctx->request_code = allowed_replies[packet_type];
+       if (packet_ctx->request_code) request_authenticator = packet_ctx->request_authenticator;
 
        /*
         *      @todo - pass in packet_ctx to this function, so that we
@@ -1787,7 +1791,8 @@ static ssize_t fr_radius_encode_proto(TALLOC_CTX *ctx, fr_pair_list_t *vps, uint
        slen = fr_radius_encode(&FR_DBUFF_TMP(data, data_len), vps, packet_ctx);
        if (slen <= 0) return slen;
 
-       if (fr_radius_sign(data, NULL, (uint8_t const *) packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1) < 0) {
+       if (fr_radius_sign(data, request_authenticator,
+                          (uint8_t const *) packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1) < 0) {
                return -1;
        }
 
index 02e4c209de939474326cb8cd9190fe6c69558a17..aa86756e01dc9eb599e9e1ec0c89f2fc7da8af64 100644 (file)
@@ -13,6 +13,26 @@ proto radius
 proto-dictionary radius
 fuzzer-out radius
 
+#
+#  For the tests, we set "secure_transport = true", so Message-Authenticator
+#  is not added automatically.
+#
+
+#
+#  No RADIUS data - we encode using random numbers from a fixed seed.
+#
+#  So encoding the same thing twice gets us the same authentication vector
+#
+encode-proto Tmp-String-0 := "foof"
+match 01 00 00 14 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+
+encode-proto Tmp-String-0 := "aaa"
+match 01 00 00 14 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+
+encode-proto Packet-Type = Access-Accept
+match 02 00 00 14 fe 5b 5a 24 2f a7 76 cb 61 5f f2 62 0a 20 e2 d9
+
+
 #
 #  1.
 #
@@ -232,5 +252,4 @@ decode-proto 02 06 00 61 fb ba 6a 78 4c 7d ec b3 14 ca f0 f2 79 44 a3 7b 08 06 f
 match Packet-Type = ::Access-Accept, Packet-Authentication-Vector = 0xfbba6a784c7decb314caf0f27944a37b, Framed-IP-Address = 255.255.255.254, Framed-MTU = 576, Service-Type = ::Framed-User, Reply-Message = "Hello, John.McGuirk", EAP-Message = 0x03010004, Message-Authenticator = 0xb9c4ae6213a71d32125ef7ca4e4c6360, User-Name = "John.McGuirk"
 
 count
-match 11
-
+match 17
index 611a0c422504dabc2002784fa271fb9a9d570a37..6c387adbc784fc6d3115cac476d5fc1df1be9a14 100644 (file)
@@ -37,6 +37,16 @@ match 45 15 00 80 6f 90 5f e5 ef e3 6f 0e a5 54 4d 7d 75 4d ea 04 c2
 decode-pair -
 match Tunnel-Password = "barbar"
 
+#
+#  Tunnel-Password is automatically skipped when it's not possible to encode it securely.
+#
+encode-proto Packet-Type = Access-Request, User-Name = "bob", Tunnel-Password = "foo", User-Password = "bob"
+match 01 00 00 2b 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 01 05 62 6f 62 02 12 f4 81 6b ca 74 fd 7a 1a 10 46 07 24 00 14 82 8b
+
+decode-proto -
+match Packet-Type = ::Access-Request, Packet-Authentication-Vector = 0x000102030405060708090a0b0c0d0e0f, User-Name = "bob", User-Password = "bob"
+
+
 #
 #  Integer attributes
 #
@@ -109,4 +119,4 @@ decode-pair -
 match Tunnel-Client-Endpoint = "\001\002\003"
 
 count
-match 45
+match 49