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".
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;
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);
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;
*/
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");
[ 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.
*/
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:
* 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;
}
* 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);
}
/*
/*
* 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 */
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,
}
}
+ 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) {
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.
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;
/*
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;
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,