Policies
Goal: Create and use policies to abstract and reuse business logic in FreeRADIUS.
Time: 10-20 minutes
Files / Directories:
-
policy.d/*(policy.d where we create and define policies) -
sites-available/default(virtual server where we call the policy)
Preparation
Look through the existing files in policy.d/ and review
other documentation sections (especially the unlang reference,
conditions, and regular expressions) to become familiar with:
-
Policy syntax
-
Attribute references (
request.,control.,reply., etc.) -
Regular expression matching in
ifconditions -
Common update operators (
:=,+=, etc.)
Policies are named blocks of unlang code that can be called almost anywhere a module can be called.
Basic structure of a policy:
policy_name {
# unlang statements here
}
Example:
You should have already created a policy named realm-split in the
Splitting Strings tutorial.
File: policy.d/realm-split
realm-split {
# Check if User-Name exists and contains an "@" symbol
if (request.User-Name =~ /^([^@]+)@(.+)$/) {
# First capture group - username part (before @)
request.Stripped-User-Name := %regex.match(1)
# Second capture group - domain/realm part (after @)
control.Stripped-User-Domain := %regex.match(2)
# Add reply attributes to validate the split worked correctly
# Using Reply-Message to show both values (visible in reply)
reply += {
Reply-Message = "User: %{request.Stripped-User-Name}"
Reply-Message = "Domain: %{control.Stripped-User-Domain}"
}
}
}
Task: Call this policy at the very beginning of the recv Access-Request
section in the default virtual server.
Open the file:
$ vi sites-available/default
Add the policy call near the top of the authorize section:
recv Access-Request {
realm-split
# ... rest of the section (chap, mschap, digest, files, etc.) ...
}
Placing it early ensures the User-Name is stripped before any local authorization modules (like files, sql, ldap, etc.) access it.
Testing
Make sure the testing user "bob" exists in mods-config/files/authorize:
Run the server in debug mode:
$ radiusd -X
Send an Access-Request with User-Name: bob@example.com
echo 'User-Name = "bob@example.com", User-Password = "hello"' | radclient -x 127.0.0.1 auth testing123
Expected output:
Received Access-Accept Id 246 from 127.0.0.1:1812 to 0.0.0.0:56242 via lo length 74
Message-Authenticator = 0x1a82a50a6973affe690efe4146e6581e
Reply-Message = "User: bob"
Reply-Message = "Domain: example.com"
User-Name = "bob"