From: Alan T. DeKok Date: Sun, 11 Aug 2024 18:18:25 +0000 (-0400) Subject: pass dbuff && packet_ctx to encode function X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ca08487afd8cdbf7763fc3886ca1f32b96860a3;p=thirdparty%2Ffreeradius-server.git pass dbuff && packet_ctx to encode function which makes it easier to add more functionality --- diff --git a/src/listen/radius/proto_radius.c b/src/listen/radius/proto_radius.c index 2d804e7bba1..e1ea57bd926 100644 --- a/src/listen/radius/proto_radius.c +++ b/src/listen/radius/proto_radius.c @@ -395,6 +395,8 @@ static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8 fr_io_address_t const *address = track->address; ssize_t data_len; fr_client_t const *client; + fr_radius_ctx_t common_ctx = {}; + fr_radius_encode_ctx_t encode_ctx; /* * Process layer NAK, or "Do not respond". @@ -457,9 +459,23 @@ static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8 request->reply->socket.inet.src_ipaddr = client->src_ipaddr; } - data_len = fr_radius_encode(buffer, buffer_len, request->packet->data, - client->secret, talloc_array_length(client->secret) - 1, - request->reply->code, request->reply->id, &request->reply_pairs); + common_ctx = (fr_radius_ctx_t) { + .secret = client->secret, + .secret_length = talloc_array_length(client->secret) - 1, + }; + encode_ctx = (fr_radius_encode_ctx_t) { + .common = &common_ctx, + .request_authenticator = request->packet->data + 4, + .rand_ctx = (fr_fast_rand_t) { + .a = fr_rand(), + .b = fr_rand(), + }, + .request_code = request->packet->data[0], + .code = request->reply->code, + .id = request->reply->id, + }; + + data_len = fr_radius_encode(&FR_DBUFF_TMP(buffer, buffer_len), &request->reply_pairs, &encode_ctx); if (data_len < 0) { RPEDEBUG("Failed encoding RADIUS reply"); return -1; diff --git a/src/modules/rlm_radius/rlm_radius_udp.c b/src/modules/rlm_radius/rlm_radius_udp.c index efb72ecad2a..46303a216e6 100644 --- a/src/modules/rlm_radius/rlm_radius_udp.c +++ b/src/modules/rlm_radius/rlm_radius_udp.c @@ -1209,6 +1209,7 @@ static int encode(rlm_radius_udp_t const *inst, request_t *request, udp_request_ uint8_t *msg = NULL; int message_authenticator = u->require_message_authenticator * (RADIUS_MESSAGE_AUTHENTICATOR_LENGTH + 2); int proxy_state = 6; + fr_radius_encode_ctx_t encode_ctx; fr_assert(inst->parent->allowed[u->code]); fr_assert(!u->packet); @@ -1237,19 +1238,8 @@ static int encode(rlm_radius_udp_t const *inst, request_t *request, udp_request_ switch (u->code) { case FR_RADIUS_CODE_ACCESS_REQUEST: case FR_RADIUS_CODE_STATUS_SERVER: - { - size_t i; - uint32_t hash, base; - message_authenticator = RADIUS_MESSAGE_AUTHENTICATOR_LENGTH + 2; - - base = fr_rand(); - for (i = 0; i < RADIUS_AUTH_VECTOR_LENGTH; i += sizeof(uint32_t)) { - hash = fr_rand() ^ base; - memcpy(u->packet + RADIUS_AUTH_VECTOR_OFFSET + i, &hash, sizeof(hash)); - } - } - FALL_THROUGH; + break; default: break; @@ -1284,13 +1274,22 @@ static int encode(rlm_radius_udp_t const *inst, request_t *request, udp_request_ */ fr_assert(u->packet_len >= (size_t) (RADIUS_HEADER_LENGTH + proxy_state + message_authenticator)); + encode_ctx = (fr_radius_encode_ctx_t) { + .common = &inst->common_ctx, + .rand_ctx = (fr_fast_rand_t) { + .a = fr_rand(), + .b = fr_rand(), + }, + .code = u->code, + .id = id, + }; + /* * Encode it, leaving room for Proxy-State and * Message-Authenticator if necessary. */ - packet_len = fr_radius_encode(u->packet, u->packet_len - (proxy_state + message_authenticator), NULL, - inst->secret, talloc_array_length(inst->secret) - 1, - u->code, id, &request->request_pairs); + packet_len = fr_radius_encode(&FR_DBUFF_TMP(u->packet, u->packet_len - (proxy_state + message_authenticator)), + &request->request_pairs, &encode_ctx); if (fr_pair_encode_is_error(packet_len)) { RPERROR("Failed encoding packet"); diff --git a/src/protocols/radius/base.c b/src/protocols/radius/base.c index f7eaf6ffd7e..07090faefbf 100644 --- a/src/protocols/radius/base.c +++ b/src/protocols/radius/base.c @@ -910,41 +910,29 @@ static const bool disallow_tunnel_passwords[FR_RADIUS_CODE_MAX] = { [ FR_RADIUS_CODE_PROTOCOL_ERROR ] = true, }; -ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *original, - char const *secret, size_t secret_len, int code, int id, fr_pair_list_t *vps) +ssize_t fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encode_ctx_t *packet_ctx) { ssize_t slen; fr_pair_t const *vp; fr_dcursor_t cursor; - fr_radius_ctx_t common_ctx = {}; - fr_radius_encode_ctx_t packet_ctx = {}; fr_dbuff_t work_dbuff, length_dbuff; - common_ctx.secret = secret; - common_ctx.secret_length = secret_len; - - packet_ctx.common = &common_ctx; - if (original) { - packet_ctx.request_authenticator = original + 4; - } else { - packet_ctx.request_authenticator = packet + 4; - } - packet_ctx.rand_ctx.a = fr_rand(); - packet_ctx.rand_ctx.b = fr_rand(); - packet_ctx.disallow_tunnel_passwords = disallow_tunnel_passwords[code]; + packet_ctx->disallow_tunnel_passwords = disallow_tunnel_passwords[packet_ctx->request_code]; /* * The RADIUS header can't do more than 64K of data. */ - work_dbuff = FR_DBUFF_TMP(packet, packet_len); + work_dbuff = FR_DBUFF_MAX(dbuff, 65535); - FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, code, id); + FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, packet_ctx->code, packet_ctx->id); length_dbuff = FR_DBUFF(&work_dbuff); FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t) RADIUS_HEADER_LENGTH); - switch (code) { + switch (packet_ctx->code) { case FR_RADIUS_CODE_ACCESS_REQUEST: case FR_RADIUS_CODE_STATUS_SERVER: + packet_ctx->request_authenticator = fr_dbuff_current(&work_dbuff); + /* * Allow over-rides of the authentication vector for testing. */ @@ -969,11 +957,11 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig case FR_RADIUS_CODE_DISCONNECT_NAK: case FR_RADIUS_CODE_PROTOCOL_ERROR: case FR_RADIUS_CODE_ACCESS_ACCEPT: - if (!original) { + if (!packet_ctx->request_authenticator) { fr_strerror_const("Cannot encode response without request"); return -1; } - FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, original + 4, RADIUS_AUTH_VECTOR_LENGTH); + FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, packet_ctx->request_authenticator, RADIUS_AUTH_VECTOR_LENGTH); break; case FR_RADIUS_CODE_ACCOUNTING_REQUEST: @@ -988,11 +976,13 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig * to say "don't do that!" */ case FR_RADIUS_CODE_COA_REQUEST: + packet_ctx->request_authenticator = fr_dbuff_current(&work_dbuff); + FR_DBUFF_MEMSET_RETURN(&work_dbuff, 0, RADIUS_AUTH_VECTOR_LENGTH); break; default: - fr_strerror_printf("Cannot encode unknown packet code %d", code); + fr_strerror_printf("Cannot encode unknown packet code %d", packet_ctx->code); return -1; } @@ -1001,9 +991,9 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig * Original-Packet-Code manually. If the user adds it * later themselves, well, too bad. */ - if (code == FR_RADIUS_CODE_PROTOCOL_ERROR) { + if (packet_ctx->code == FR_RADIUS_CODE_PROTOCOL_ERROR) { FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_EXTENDED_ATTRIBUTE_1, 0x07, 0x04 /* Original-Packet-Code */, - 0x00, 0x00, 0x00, original[0]); + 0x00, 0x00, 0x00, packet_ctx->request_code); } /* @@ -1016,7 +1006,7 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig /* * Encode an individual VP */ - slen = fr_radius_encode_pair(&work_dbuff, &cursor, &packet_ctx); + slen = fr_radius_encode_pair(&work_dbuff, &cursor, packet_ctx); if (slen < 0) return slen; } /* done looping over all attributes */ @@ -1028,7 +1018,7 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "%s encoded packet", __FUNCTION__); - return fr_dbuff_used(&work_dbuff); + return fr_dbuff_set(dbuff, &work_dbuff); } ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index 20cc6deb674..2c3b438e5ad 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -1738,12 +1738,13 @@ static ssize_t fr_radius_encode_proto(TALLOC_CTX *ctx, fr_pair_list_t *vps, uint } } + packet_ctx->code = packet_type; + /* * @todo - pass in packet_ctx to this function, so that we * can leverage a consistent random number generator. */ - slen = fr_radius_encode(data, data_len, NULL, packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1, - packet_type, 0, vps); + 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) { diff --git a/src/protocols/radius/packet.c b/src/protocols/radius/packet.c index 511ebe2bce7..5c41f797379 100644 --- a/src/protocols/radius/packet.c +++ b/src/protocols/radius/packet.c @@ -52,8 +52,9 @@ typedef struct { ssize_t fr_packet_encode(fr_packet_t *packet, fr_pair_list_t *list, fr_packet_t const *original, char const *secret) { - uint8_t const *original_data; ssize_t slen; + fr_radius_ctx_t common = {}; + fr_radius_encode_ctx_t packet_ctx; /* * A 4K packet, aligned on 64-bits. @@ -64,19 +65,22 @@ ssize_t fr_packet_encode(fr_packet_t *packet, fr_pair_list_t *list, if (fr_debug_lvl >= L_DBG_LVL_4) fr_packet_log_hex(&default_log, packet); #endif - if (original) { - original_data = original->data; - } else { - original_data = NULL; - } - - /* - * This has to be initialized for Access-Request packets - */ - memcpy(data + 4, packet->vector, sizeof(packet->vector)); - - slen = fr_radius_encode(data, sizeof(data), original_data, secret, talloc_array_length(secret) - 1, - packet->code, packet->id, list); + common.secret = secret; + common.secret_length = talloc_array_length(secret) - 1; + + packet_ctx = (fr_radius_encode_ctx_t) { + .common = &common, + .request_authenticator = original ? original->data + 4 : NULL, + .rand_ctx = (fr_fast_rand_t) { + .a = fr_rand(), + .b = fr_rand(), + }, + .request_code = original ? original->data[0] : 0, + .code = packet->code, + .id = packet->id, + }; + + slen = fr_radius_encode(&FR_DBUFF_TMP(data, sizeof(data)), list, &packet_ctx); if (slen < 0) return slen; /* diff --git a/src/protocols/radius/radius.h b/src/protocols/radius/radius.h index 852714c80d6..ce8cdaa49ed 100644 --- a/src/protocols/radius/radius.h +++ b/src/protocols/radius/radius.h @@ -156,6 +156,11 @@ typedef struct { uint8_t tag; //!< current tag for encoding + uint8_t request_code; + + uint8_t code; + uint32_t id; + bool disallow_tunnel_passwords; //!< not all packets can have tunnel passwords bool seen_message_authenticator; } fr_radius_encode_ctx_t; @@ -211,8 +216,7 @@ ssize_t fr_radius_ascend_secret(fr_dbuff_t *dbuff, uint8_t const *in, size_t in ssize_t fr_radius_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, unsigned int *code); -ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *original, - char const *secret, size_t secret_len, int code, int id, fr_pair_list_t *vps); +ssize_t fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encode_ctx_t *packet_ctx) CC_HINT(nonnull); ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len,