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);
}
/*
/*
* 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);
}
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(),
};
/*
* 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);
}