FreeRADIUS InkBridge

Protocol-Error Implementation

The following is a set of notes for implementing Protocol-Error in FreeRADIUS 3.2.

Client Configuration

Each client now has an additional configuration option:

protocol_error = yes # default is "no"

This configuration option is also exposed as in internal attribute for dynamic clients.

The purpose of this option is to control whether or not we send a Protocol-Error response to the client. Previous versions of the server would synthesize an Access-Reject in some circumstances, and we don’t want to change that behavior in a stable release.

All new behavior for sending Protocol-Error to a client is enabled by setting this flag.

Encoder / Decoder

The encoder and decoder have been updated to allow Protocol-Error.

Encoder

The encoder has been updated to encode Protocol-Error as response packets. The encoding method used is the same as for Access-Accept, etc. This encoding means that Message-Authenticator is also added for all Protocol-Error packets, even for ones which are in response to Accounting-Request. We may be OK with relaxing this requirement in the future.

The only magic in the encoder is that it automatically adds Original-Packet-Code. This attribute allows the client to associate the Protocol-Error responsewith (e.g.) Access-Request or Accounting-Request, even if both of those packets contain the same ID.

i.e. there is no need for the RADIUS policies to add Original-Packet-Code. Since that attribute is required for protocol compliance, the encoder adds it automatically.

FreeRADIUS tracks packets by ID, and not by packet Code. So this attribute isn’t necessary. But maybe other RADIUS implementations need it.

Decoder

The decoder has been updated to decode Protocol-Error as response packets for any request.

Other than that, the decoder did not require any changes.

radclient

radclient was updated to explicitly accept Protocol-Error as a response to Access-Request packets. Note that only the BlastRADIUS checks needed to be updated, because they checked the packet codes before calling the decoder.

Since the decoder was updated to allow Protocol-Error, no additional changes to radclient were needed.

Server

The server had a number of changes in order to support Protocol-Error.

Input Queue

When the server is busy and cannot enqueue a new packet, it previously just discarded the request.

It now checks if the client supports Protocol-Error. If so, it immediately encodes and sends a Protocol-Error response. The request is also marked up as done/completed/cleaned-up immediately. Since the server is busy, there isn’t much utility in caching the packet for a "cleanup delay".

We may want to add "cleanup delay" handling in the future.

Modules

The realm module has been updated to configurable return notfound when the destination realm isn’t found. As this is a behavior change, it is hidden behind a new module configuration flag

return_notfound = yes # default is "no"

Default Virtual Server

The default virtual server has been updated with a commented-out configuration for Protocol-Error. The configuration is after the suffix module, which is used for routing packets based on realms:

authorize {
	...
	suffix
	if (notfound && ("%{client:protocol_error}" == "yes")) {
		update {
		       &control:Response-Packet-Type := Protocol-Error
		       &reply:Error-Cause := Proxy-Request-Not-Routable
		}
	       handled
	}
	...
}

Proxied Requests

No changes are made to proxied requests.

Proxied Responses

The server always accepts Protocol-Error as a response to any proxied request. This behavior is not configurable. There doesn’t seem to be any good reason to ignore/discard Protocol-Error responses.

If the server never receives a reply from the home server, it checks if the client can receive Protocol-Error. If so, it synthesizes a Protocol-Error reply, and runs it through the "proxcess proxy reply" functionality. It also adds an Error-Cause with a value that is appropriate for what happened.

If the server never receives a reply from the home server, a policy in the Post-Proxy-Type section can still manually create a Protocol-Error packet. This is allowed because maybe there’s a situation where checking the client protocol_error flag isn’t enough. Again, it also adds (if necessary) an Error-Cause with a value that is appropriate for what happened. If the policy added Error-Cause, then that value isn’t changed.

The server does not re-proxy the packet if it receives a Protocol-Error response from the home server.

Finished Processing, Sending Response

Once a request is done processing, a response is sent. Since not all clients support Protocol-Error, the code checks if a policy (or home server) created a Protocol-Error response. If it is there, the packet code is mashed to "no reply".

This change allows the rest of the code to determine what response (if any) is sent. For example, the historic behavior for Access-Request is to send a synthesized Access-Reject.