Note recent changes
[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         #       Forbid all EAP types.
24         #
25         forbid_eap {
26                 if (EAP-Message) {
27                         reject
28                 }
29         }
30
31         #
32         #       Forbid all non-EAP types outside of an EAP tunnel.
33         #
34         permit_only_eap {
35                 if (!EAP-Message) {
36                         #  We MAY be inside of a TTLS tunnel.
37                         #  PEAP and EAP-FAST require EAP inside of
38                         #  the tunnel, so this check is OK.
39                         #  If so, then there MUST be an outer EAP message.
40                         if (!"%{outer.request:EAP-Message}") {
41                                 reject
42                         }
43                 }
44         }
45
46         #
47         #       Forbid all attempts to login via realms.
48         #
49         deny_realms {
50                 if (User-Name =~ /@|\\/) {
51                         reject
52                 }
53         }
54
55         #
56         #       If you want the server to pretend that it is dead,
57         #       then use the "do_not_respond" policy.
58         #
59         do_not_respond {
60                 update control {
61                         Response-Packet-Type := Do-Not-Respond
62                 }
63
64                 handled
65         }
66
67         #
68         #  Force some sanity on User-Name.  This helps to avoid issues
69         #  issues where the back-end database is "forgiving" about
70         #  what constitutes a user name.
71         #
72         filter_username {
73                 
74                 #
75                 #  reject mixed case
76                 #  e.g. "UseRNaMe"
77                 #
78                 #if (User-Name != "%{tolower:%{User-Name}}") {
79                 #       reject
80                 #}
81
82                 #
83                 #  reject all whitespace
84                 #  e.g. "user@ site.com", or "us er", or " user", or "user "
85                 #
86                 if (User-Name =~ / /) {
87                         update reply {
88                                 Reply-Message += "Rejected: Username contains whitespace"
89                         }
90                         reject
91                 }
92
93                 #
94                 #  reject Multiple @'s
95                 #  e.g. "user@site.com@site.com"
96                 #
97                 if(User-Name =~ /@.*@/ ) {
98                         update reply {
99                                 Reply-Message += "Rejected: Multiple @ in username"
100                         }
101                         reject
102                 }
103
104                 #
105                 #  reject double dots
106                 #  e.g. "user@site..com"
107                 #
108                 if (User-Name =~ /\\.\\./ ) {
109                         update reply {
110                                 Reply-Message += "Rejected: Username comtains ..s"
111                         }
112                         reject
113                 }
114
115                 #
116                 #  must have at least 1 string-dot-string after @
117                 #  e.g. "user@site.com"
118                 #
119                 if (User-Name !~ /@(.+)\\.(.+)$/)  {
120                         update reply {
121                                 Reply-Message += "Rejected: Realm does not have at least one dot seperator"
122                         }
123                         reject
124                 }
125
126                 #
127                 #  Realm ends with a dot
128                 #  e.g. "user@site.com."
129                 #
130                 if (User-Name =~ /\\.$/)  {
131                         update reply {
132                                 Reply-Message += "Rejected: Realm ends with a dot"
133                         }
134                         reject
135                 }
136
137                 #
138                 #  Realm begins with a dot
139                 #  e.g. "user@.site.com"
140                 #
141                 if (User-Name =~ /@\\./)  {
142                         update reply {
143                                 Reply-Message += "Rejected: Realm begins with a dot"
144                         }
145                         reject
146                 }
147         }
148
149         #       
150         #  The following policies are for the Chargeable-User-Identity
151         #  (CUI) configuration.
152         #
153
154         #
155         #  The client indicates it can do CUI by sending a CUI attribute        
156         #  containing one zero byte
157         #
158         cui_authorize {
159                 update request {
160                         Chargeable-User-Identity:='\\000'
161                 }
162         }
163
164         #
165         #  Add a CUI attribute based on the User-Name, and a secret key
166         #  known only to this server.
167         #
168         cui_postauth {
169                 if (FreeRadius-Proxied-To == 127.0.0.1) {
170                         if (outer.request:Chargeable-User-Identity) {
171                                 update outer.reply {
172                                         Chargeable-User-Identity:="%{md5:%{config:cui_hash_key}%{User-Name}}"
173                                 }
174                         }
175                 }
176                 else {
177                         if (Chargeable-User-Identity) {
178                                 update reply {
179                                         Chargeable-User-Identity="%{md5:%{config:cui_hash_key}%{User-Name}}"
180                                 }
181                         }
182                 }
183         }
184
185         #
186         #  If there is a CUI attribute in the reply, add it to the DB.
187         #
188         cui_updatedb {
189                 if (reply:Chargeable-User-Identity) {
190                         cui
191                 }
192         }
193
194         #
195         #  If we had stored a CUI for the User, add it to the request.
196         #
197         cui_accounting {
198                 #
199                 #  If the CUI isn't in the packet, see if we can find it
200                 #  in the DB.
201                 #
202                 if (!Chargeable-User-Identity) {
203                         update request {
204                                 Chargeable-User-Identity := "%{cui: SELECT cui FROM cui WHERE clientipaddress = '%{Client-IP-Address}' AND callingstationid = '%{Calling-Station-Id}' AND username = '%{User-Name}'}"
205                         }
206                 }
207
208                 #
209                 #  If it exists now, then write out when we last saw
210                 #  this CUI.
211                 #
212                 if (Chargeable-User-Identity && (Chargeable-User-Identity != "")) {
213                         cui
214                 }
215         }
216
217         #
218         #  Normalize the MAC Addresses in the Calling/Called-Station-Id
219         #
220         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})
221
222         #  Add "rewrite.called_station_id" in the "authorize" and "preacct"
223         #  sections.
224         rewrite.called_station_id {
225                 if((Called-Station-Id) && "%{Called-Station-Id}" =~ /^%{config:policy.mac-addr}(:(.+))?$/i) {
226                         update request {
227                                 Called-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
228                         }
229
230                         # SSID component?
231                         if ("%{8}") {
232                                 update request {
233                                         Called-Station-Id := "%{Called-Station-Id}:%{8}"
234                                 }
235                         }
236                         updated
237                 }
238                 else {
239                         noop
240                 }
241         }
242
243         #  Add "rewrite.calling_station_id" in the "authorize" and "preacct"
244         #  sections.
245         rewrite.calling_station_id {
246                 if((Calling-Station-Id) && "%{Calling-Station-Id}" =~ /^%{config:policy.mac-addr}$/i) {
247                         update request {
248                                 Calling-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
249                         }
250                         updated
251                 }
252                 else {
253                         noop
254                 }
255         }
256
257         #  Assign compatibility data to request for sqlippool
258         dhcp_sqlippool.post-auth {
259
260
261                 #  Do some minor hacks to the request so that it looks
262                 #  like a RADIUS request to the SQL IP Pool module.
263                 update request {
264                         User-Name = "DHCP-%{DHCP-Client-Hardware-Address}"
265                         Calling-Station-Id = "%{DHCP-Client-Hardware-Address}"
266                         NAS-IP-Address = "%{%{DHCP-Gateway-IP-Address}:-127.0.0.1}"
267                         Acct-Status-Type = Start
268                 }
269
270                 #  Call the actual module
271                 #
272                 #  Uncomment this in order to really call it!
273 #               dhcp_sqlippool
274                 fail
275
276                 #  Convert Framed-IP-Address to DHCP, but only if we
277                 #  actually allocated an address.
278                 if (ok) {
279                         update reply {
280                                 DHCP-Your-IP-Address = "%{reply:Framed-IP-Address}"
281                         }
282                 }
283         }
284 }