diff --git a/src/modules/rlm_radius/bio.c b/src/modules/rlm_radius/bio.c index 8bc203f9103d..94602671b0c6 100644 --- a/src/modules/rlm_radius/bio.c +++ b/src/modules/rlm_radius/bio.c @@ -1243,7 +1243,7 @@ static int encode(bio_handle_t *h, request_t *request, bio_request_t *u, uint8_t MEM(vp = fr_pair_afrom_da(u->packet, attr_proxy_state)); fr_pair_value_memdup(vp, (uint8_t const *) &inst->common_ctx.proxy_state, sizeof(inst->common_ctx.proxy_state), false); fr_pair_append(&u->extra, vp); - packet_len += 6; + packet_len += 2 + sizeof(inst->common_ctx.proxy_state); } /* @@ -1527,21 +1527,37 @@ static void request_mux(UNUSED fr_event_list_t *el, /* * Warn people about misconfigurations and loops. + * + * There should _never_ be two instances of the same Proxy-State in the packet. */ if (RDEBUG_ENABLED && u->proxied) { + unsigned int count = 0; + fr_pair_list_foreach(&request->request_pairs, vp) { if (vp->vp_length != sizeof(h->ctx.radius_ctx.proxy_state)) continue; if (memcmp(vp->vp_octets, &h->ctx.radius_ctx.proxy_state, sizeof(h->ctx.radius_ctx.proxy_state)) == 0) { + + /* + * Cancel proxying when there are two instances of the same Proxy-State + * in the packet. This limitation could be configurable, but it likely + * doesn't make sense to make it configurable. + */ + if (count == 1) { + RWARN("Canceling proxy due to loop of multiple %pV", vp); + trunk_request_signal_cancel(treq); + u->treq = NULL; + return; + } + RWARN("Proxied packet contains our own %pV", vp); RWARN("Check if there is a proxy loop. Perhaps the server has been configured to proxy to itself."); - break; + count++; } } } - mod_write(request, treq, h); } diff --git a/src/modules/rlm_radius/rlm_radius.c b/src/modules/rlm_radius/rlm_radius.c index d564673b5caa..d26003877023 100644 --- a/src/modules/rlm_radius/rlm_radius.c +++ b/src/modules/rlm_radius/rlm_radius.c @@ -693,7 +693,7 @@ static int mod_instantiate(module_inst_ctx_t const *mctx) inst->common_ctx = (fr_radius_ctx_t) { .secret = inst->secret, .secret_length = inst->secret ? talloc_array_length(inst->secret) - 1 : 0, - .proxy_state = fr_rand(), + .proxy_state = ((uint64_t) fr_rand()) << 32 | fr_rand(), }; /* diff --git a/src/protocols/radius/base.c b/src/protocols/radius/base.c index 5fbeea61a178..22440fec0391 100644 --- a/src/protocols/radius/base.c +++ b/src/protocols/radius/base.c @@ -1070,7 +1070,7 @@ ssize_t fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encod * Add Proxy-State to the end of the packet if the caller requested it. */ if (packet_ctx->add_proxy_state) { - FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_PROXY_STATE, 6); + FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_PROXY_STATE, (uint8_t) (2 + sizeof(packet_ctx->common->proxy_state))); FR_DBUFF_IN_RETURN(&work_dbuff, packet_ctx->common->proxy_state); } diff --git a/src/protocols/radius/client.h b/src/protocols/radius/client.h index c5fd9bb79985..f243bd836c34 100644 --- a/src/protocols/radius/client.h +++ b/src/protocols/radius/client.h @@ -44,7 +44,7 @@ typedef struct { fr_time_delta_t connection_timeout; bool add_proxy_state; - uint32_t proxy_state; + uint64_t proxy_state; bool outgoing[FR_RADIUS_CODE_MAX]; //!< allowed outgoing packet types diff --git a/src/protocols/radius/radius.h b/src/protocols/radius/radius.h index e019f9c9c069..d9d4676f0b02 100644 --- a/src/protocols/radius/radius.h +++ b/src/protocols/radius/radius.h @@ -97,7 +97,7 @@ typedef struct { bool secure_transport; //!< for TLS - uint32_t proxy_state; //!< if so, this is its value + uint64_t proxy_state; } fr_radius_ctx_t; typedef struct {