forked from infra/ansible
285 lines
6.3 KiB
Plaintext
285 lines
6.3 KiB
Plaintext
|
# -*- text -*-
|
||
|
##
|
||
|
## policy.conf -- FreeRADIUS server configuration file.
|
||
|
##
|
||
|
## http://www.freeradius.org/
|
||
|
## $Id: e8a85759279dae0e6e7bd340f53c0adcbc128bf9 $
|
||
|
##
|
||
|
|
||
|
#
|
||
|
# Policies are virtual modules, similar to those defined in the
|
||
|
# "instantate" section of radiusd.conf.
|
||
|
#
|
||
|
# Defining a policy here means that it can be referenced in multiple
|
||
|
# places as a *name*, rather than as a series of conditions to match,
|
||
|
# and actions to take.
|
||
|
#
|
||
|
# Policies are something like subroutines in a normal language, but
|
||
|
# they cannot be called recursively. They MUST be defined in order.
|
||
|
# If policy A calls policy B, then B MUST be defined before A.
|
||
|
#
|
||
|
policy {
|
||
|
#
|
||
|
# Forbid all EAP types.
|
||
|
#
|
||
|
forbid_eap {
|
||
|
if (EAP-Message) {
|
||
|
reject
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Forbid all non-EAP types outside of an EAP tunnel.
|
||
|
#
|
||
|
permit_only_eap {
|
||
|
if (!EAP-Message) {
|
||
|
# We MAY be inside of a TTLS tunnel.
|
||
|
# PEAP and EAP-FAST require EAP inside of
|
||
|
# the tunnel, so this check is OK.
|
||
|
# If so, then there MUST be an outer EAP message.
|
||
|
if (!"%{outer.request:EAP-Message}") {
|
||
|
reject
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Forbid all attempts to login via realms.
|
||
|
#
|
||
|
deny_realms {
|
||
|
if (User-Name =~ /@|\\/) {
|
||
|
reject
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# If you want the server to pretend that it is dead,
|
||
|
# then use the "do_not_respond" policy.
|
||
|
#
|
||
|
do_not_respond {
|
||
|
update control {
|
||
|
Response-Packet-Type := Do-Not-Respond
|
||
|
}
|
||
|
|
||
|
handled
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Force some sanity on User-Name. This helps to avoid issues
|
||
|
# issues where the back-end database is "forgiving" about
|
||
|
# what constitutes a user name.
|
||
|
#
|
||
|
filter_username {
|
||
|
|
||
|
#
|
||
|
# reject mixed case
|
||
|
# e.g. "UseRNaMe"
|
||
|
#
|
||
|
#if (User-Name != "%{tolower:%{User-Name}}") {
|
||
|
# reject
|
||
|
#}
|
||
|
|
||
|
#
|
||
|
# reject all whitespace
|
||
|
# e.g. "user@ site.com", or "us er", or " user", or "user "
|
||
|
#
|
||
|
if (User-Name =~ / /) {
|
||
|
update reply {
|
||
|
Reply-Message += "Rejected: Username contains whitespace"
|
||
|
}
|
||
|
reject
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# reject Multiple @'s
|
||
|
# e.g. "user@site.com@site.com"
|
||
|
#
|
||
|
if(User-Name =~ /@.*@/ ) {
|
||
|
update reply {
|
||
|
Reply-Message += "Rejected: Multiple @ in username"
|
||
|
}
|
||
|
reject
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# reject double dots
|
||
|
# e.g. "user@site..com"
|
||
|
#
|
||
|
if (User-Name =~ /\\.\\./ ) {
|
||
|
update reply {
|
||
|
Reply-Message += "Rejected: Username comtains ..s"
|
||
|
}
|
||
|
reject
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# must have at least 1 string-dot-string after @
|
||
|
# e.g. "user@site.com"
|
||
|
#
|
||
|
if (User-Name !~ /@(.+)\\.(.+)$/) {
|
||
|
update reply {
|
||
|
Reply-Message += "Rejected: Realm does not have at least one dot seperator"
|
||
|
}
|
||
|
reject
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Realm ends with a dot
|
||
|
# e.g. "user@site.com."
|
||
|
#
|
||
|
if (User-Name =~ /\\.$/) {
|
||
|
update reply {
|
||
|
Reply-Message += "Rejected: Realm ends with a dot"
|
||
|
}
|
||
|
reject
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Realm begins with a dot
|
||
|
# e.g. "user@.site.com"
|
||
|
#
|
||
|
if (User-Name =~ /@\\./) {
|
||
|
update reply {
|
||
|
Reply-Message += "Rejected: Realm begins with a dot"
|
||
|
}
|
||
|
reject
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# The following policies are for the Chargeable-User-Identity
|
||
|
# (CUI) configuration.
|
||
|
#
|
||
|
|
||
|
#
|
||
|
# The client indicates it can do CUI by sending a CUI attribute
|
||
|
# containing one zero byte
|
||
|
#
|
||
|
cui_authorize {
|
||
|
update request {
|
||
|
Chargeable-User-Identity:='\\000'
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Add a CUI attribute based on the User-Name, and a secret key
|
||
|
# known only to this server.
|
||
|
#
|
||
|
cui_postauth {
|
||
|
if (FreeRadius-Proxied-To == 127.0.0.1) {
|
||
|
if (outer.request:Chargeable-User-Identity) {
|
||
|
update outer.reply {
|
||
|
Chargeable-User-Identity:="%{md5:%{config:cui_hash_key}%{User-Name}}"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (Chargeable-User-Identity) {
|
||
|
update reply {
|
||
|
Chargeable-User-Identity="%{md5:%{config:cui_hash_key}%{User-Name}}"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# If there is a CUI attribute in the reply, add it to the DB.
|
||
|
#
|
||
|
cui_updatedb {
|
||
|
if (reply:Chargeable-User-Identity) {
|
||
|
cui
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# If we had stored a CUI for the User, add it to the request.
|
||
|
#
|
||
|
cui_accounting {
|
||
|
#
|
||
|
# If the CUI isn't in the packet, see if we can find it
|
||
|
# in the DB.
|
||
|
#
|
||
|
if (!Chargeable-User-Identity) {
|
||
|
update request {
|
||
|
Chargeable-User-Identity := "%{cui: SELECT cui FROM cui WHERE clientipaddress = '%{Client-IP-Address}' AND callingstationid = '%{Calling-Station-Id}' AND username = '%{User-Name}'}"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# If it exists now, then write out when we last saw
|
||
|
# this CUI.
|
||
|
#
|
||
|
if (Chargeable-User-Identity && (Chargeable-User-Identity != "")) {
|
||
|
cui
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Normalize the MAC Addresses in the Calling/Called-Station-Id
|
||
|
#
|
||
|
mac-addr = ([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})
|
||
|
|
||
|
# Add "rewrite.called_station_id" in the "authorize" and "preacct"
|
||
|
# sections.
|
||
|
rewrite.called_station_id {
|
||
|
if((Called-Station-Id) && "%{Called-Station-Id}" =~ /^%{config:policy.mac-addr}(:(.+))?$/i) {
|
||
|
update request {
|
||
|
Called-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
|
||
|
}
|
||
|
|
||
|
# SSID component?
|
||
|
if ("%{8}") {
|
||
|
update request {
|
||
|
Called-Station-Id := "%{Called-Station-Id}:%{8}"
|
||
|
}
|
||
|
}
|
||
|
updated
|
||
|
}
|
||
|
else {
|
||
|
noop
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Add "rewrite.calling_station_id" in the "authorize" and "preacct"
|
||
|
# sections.
|
||
|
rewrite.calling_station_id {
|
||
|
if((Calling-Station-Id) && "%{Calling-Station-Id}" =~ /^%{config:policy.mac-addr}$/i) {
|
||
|
update request {
|
||
|
Calling-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
|
||
|
}
|
||
|
updated
|
||
|
}
|
||
|
else {
|
||
|
noop
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Assign compatibility data to request for sqlippool
|
||
|
dhcp_sqlippool.post-auth {
|
||
|
|
||
|
|
||
|
# Do some minor hacks to the request so that it looks
|
||
|
# like a RADIUS request to the SQL IP Pool module.
|
||
|
update request {
|
||
|
User-Name = "DHCP-%{DHCP-Client-Hardware-Address}"
|
||
|
Calling-Station-Id = "%{DHCP-Client-Hardware-Address}"
|
||
|
NAS-IP-Address = "%{%{DHCP-Gateway-IP-Address}:-127.0.0.1}"
|
||
|
Acct-Status-Type = Start
|
||
|
}
|
||
|
|
||
|
# Call the actual module
|
||
|
#
|
||
|
# Uncomment this in order to really call it!
|
||
|
# dhcp_sqlippool
|
||
|
fail
|
||
|
|
||
|
# Convert Framed-IP-Address to DHCP, but only if we
|
||
|
# actually allocated an address.
|
||
|
if (ok) {
|
||
|
update reply {
|
||
|
DHCP-Your-IP-Address = "%{reply:Framed-IP-Address}"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|