Fixup CUI policies to use the new overloading behaviour
[freeradius.git] / raddb / policy.conf
1 # -*- text -*-
2 ##
3 ## policy.conf  -- FreeRADIUS server configuration file.
4 ##
5 ##      http://www.freeradius.org/
6 ##      $Id$
7 ##
8
9 #
10 #  Policies are virtual modules, similar to those defined in the
11 #  "instantate" section of radiusd.conf.
12 #
13 #  Defining a policy here means that it can be referenced in multiple
14 #  places as a *name*, rather than as a series of conditions to match,
15 #  and actions to take.
16 #
17 #  Policies are something like subroutines in a normal language, but
18 #  they cannot be called recursively. They MUST be defined in order.
19 #  If policy A calls policy B, then B MUST be defined before A.
20 #
21 policy {
22         #
23         #       Overload the default acct_unique module, it's not smart enough
24         #
25         acct_unique {
26                 #
27                 #  If we have a class attribute, it'll have a local value (defined by populate_class),
28                 #  this ensures uniqueness and suitability.
29                 #  We could just use the Class attribute as Acct-Unique-Session-Id, but this may cause
30                 #  problems with NAS that carry Class values across between multiple linked sessions.
31                 #  So we rehash class with Acct-Session-ID to provide a truely unique session identifier.
32                 #
33                 #  Using a Class/Session-ID combination is more robust than using elements in the
34                 #  Accounting-Request, which may be subject to change, such as NAS-IP-Address
35                 #  or Client-IP-Address and NAS-Port-ID/NAS-Port.
36                 #  So should ensure that session data is not affected if NAS IP addresses change, or
37                 #  the client roams to a different 'port' whilst maintaining its initial authentication
38                 #  session (Common in a wireless environment).
39                 #        
40                 if(Class) {
41                         update request {
42                                 Acct-Unique-Session-Id := "%{md5:%{Class}%{Acct-Session-ID}}"
43                         }
44                 }        
45                 #
46                 #  Not All devices respect RFC 2865 when dealing with the class attribute,
47                 #  so be prepared to use the older style of hashing scheme if a class attribute is not included 
48                 #
49                 else {
50                         update request {
51                                 Acct-Unique-Session-Id := "%{md5:%{User-Name}%{Acct-Session-ID}%{NAS-IP-Address}%{NAS-Port-ID:}%{NAS-Port}}" 
52                          }       
53                 }        
54         }        
55
56         #
57         #       Insert a (hopefully unique) value into class
58         #
59         insert_acct_class {
60                 update reply { 
61                         Class = "%{md5:%t%{request:NAS-Identifier}%{NAS-Port-ID}%{NAS-Port}%{Calling-Station-ID}%{reply:User-Name}}"
62                 }
63         }
64
65         #
66         #       Forbid all EAP types.
67         #
68         forbid_eap {
69                 if (EAP-Message) {
70                         reject
71                 }
72         }
73
74         #
75         #       Forbid all non-EAP types outside of an EAP tunnel.
76         #
77         permit_only_eap {
78                 if (!EAP-Message) {
79                         #  We MAY be inside of a TTLS tunnel.
80                         #  PEAP and EAP-FAST require EAP inside of
81                         #  the tunnel, so this check is OK.
82                         #  If so, then there MUST be an outer EAP message.
83                         if (!"%{outer.request:EAP-Message}") {
84                                 reject
85                         }
86                 }
87         }
88
89         #
90         #       Forbid all attempts to login via realms.
91         #
92         deny_realms {
93                 if (User-Name =~ /@|\\/) {
94                         reject
95                 }
96         }
97
98         #
99         #  If you want the server to pretend that it is dead,
100         #  then use the "do_not_respond" policy.
101         #
102         do_not_respond {
103                 update control {
104                         Response-Packet-Type := Do-Not-Respond
105                 }
106
107                 handled
108         }
109
110         #
111         #       Filter the username
112         #
113         #  Force some sanity on User-Name.This helps to avoid issues
114         #  issues where the back-end database is "forgiving" about
115         #  what constitutes a user name.
116         #
117         filter_username {
118                 # spaces at the start: reject
119                 if (User-Name =~ /^ /) {
120                         reject
121                 }
122
123                 # spaces at the end: reject
124                 if (User-Name =~ / $$/) {
125                         reject
126                 }
127
128                 # Mixed case: reject
129                 if (User-Name != "%{tolower:%{User-Name}}") {
130                         reject
131                 }
132         }
133
134
135         #       
136         #  The following policies are for the Chargeable-User-Identity
137         #  (CUI) configuration.
138
139         #
140         #  The policies below can be called as just 'cui' (not cui.authorize etc..)
141         #  from the various  config sections.   
142         #
143
144         #
145         #  The client indicates it can do CUI by sending a CUI attribute        
146         #  containing one zero byte
147         #
148         cui.authorize {
149                 update request {
150                         Chargeable-User-Identity:='\\000'
151                 }
152         }
153
154         #
155         #  Add a CUI attribute based on the User-Name, and a secret key
156         #  known only to this server.
157         #
158         cui.postauth {
159                 if (FreeRadius-Proxied-To == 127.0.0.1) {
160                         if (outer.request:Chargeable-User-Identity) {
161                                 update outer.reply {
162                                         Chargeable-User-Identity:="%{md5:%{config:cui_hash_key}%{User-Name}}"
163                                 }
164                         }
165                 }
166                 else {
167                         if (Chargeable-User-Identity) {
168                                 update reply {
169                                         Chargeable-User-Identity="%{md5:%{config:cui_hash_key}%{User-Name}}"
170                                 }
171                         }
172                 }
173         }
174
175
176         #
177         #  If we had stored a CUI for the User, add it to the request.
178         #
179         cui.accounting {
180                 #
181                 #  If the CUI isn't in the packet, see if we can find it
182                 #  in the DB.
183                 #
184                 if (!Chargeable-User-Identity) {
185                         update control {
186                                 Chargable-User-Identity := "%{cui: SELECT cui FROM cui WHERE clientipaddress = '%{Client-IP-Address}' AND callingstationid = '%{Calling-Station-Id}' AND username = '%{User-Name}'}"
187                         }
188                 }
189
190                 #
191                 #  If it exists now, then write out when we last saw
192                 #  this CUI.
193                 #
194                 if (Chargeable-User-Identity && (Chargeable-User-Identity != "")) {
195                         cui
196                 }
197         }
198
199         #
200         #  If there is a CUI attribute in the reply, add it to the DB.
201         #
202         cui_updatedb {
203                 if (reply:Chargeable-User-Identity) {
204                         cui
205                 }
206         }
207
208         #
209         #  Normalize the MAC Addresses in the Calling/Called-Station-Id
210         #
211         mac-addr-regexp = ([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})
212
213         #  Add "rewrite_called_station_id" in the "authorize" and "preacct"
214         #  sections.
215         rewrite_called_station_id {
216                 if(Called-Station-Id =~ /^%{config:policy.mac-addr-regexp}(:(.+))?$/i) {
217                         update request {
218                                 Called-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
219                         }
220
221                         # SSID component?
222                         if ("%{7}") {
223                                 update request {
224                                         Called-Station-SSID := "%{7}"
225                                 }
226                         }
227                         updated
228                 }
229                 else {
230                         noop
231                 }
232         }
233
234         #  Add "rewrite_calling_station_id" in the "authorize" and "preacct"
235         #  sections.
236         rewrite_calling_station_id {
237                 if(Calling-Station-Id =~ /^%{config:policy.mac-addr-regexp}$/i) {
238                         update request {
239                                 Calling-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
240                         }
241                         updated
242                 }
243                 else {
244                         noop
245                 }
246         }
247 }