From: Alan T. DeKok Date: Sat, 10 Jan 2026 13:10:29 +0000 (-0500) Subject: allow encode/decode of response packets, too X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62cc841b1425df44f43b9eb95055e5c2d09916cd;p=thirdparty%2Ffreeradius-server.git allow encode/decode of response packets, too --- diff --git a/src/protocols/radius/attrs.h b/src/protocols/radius/attrs.h index 1cdf526e62b..5b5981c3b3c 100644 --- a/src/protocols/radius/attrs.h +++ b/src/protocols/radius/attrs.h @@ -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]; diff --git a/src/protocols/radius/base.c b/src/protocols/radius/base.c index d6bce6afccf..2ebc2e2c5d2 100644 --- a/src/protocols/radius/base.c +++ b/src/protocols/radius/base.c @@ -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, diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index 48c3b070daf..6773ee45f06 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -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; } diff --git a/src/tests/unit/protocols/radius/packet_radius.txt b/src/tests/unit/protocols/radius/packet_radius.txt index 02e4c209de9..aa86756e01d 100644 --- a/src/tests/unit/protocols/radius/packet_radius.txt +++ b/src/tests/unit/protocols/radius/packet_radius.txt @@ -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 diff --git a/src/tests/unit/protocols/radius/rfc2868.txt b/src/tests/unit/protocols/radius/rfc2868.txt index 611a0c42250..6c387adbc78 100644 --- a/src/tests/unit/protocols/radius/rfc2868.txt +++ b/src/tests/unit/protocols/radius/rfc2868.txt @@ -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