2 * rlm_policy.c Implements a policy language
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2004 Alan DeKok <aland@ox.org>
21 * Copyright 2006 The FreeRADIUS server project
24 #include <freeradius-devel/ident.h>
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
30 #include "rlm_policy.h"
33 * A mapping of configuration file names to internal variables.
35 * Note that the string is dynamically allocated, so it MUST
36 * be freed. When the configuration file parse re-reads the string,
37 * it free's the old one, and strdup's the new one, placing the pointer
38 * to the strdup'd string into 'config.string'. This gets around
41 static const CONF_PARSER module_config[] = {
42 { "filename", PW_TYPE_FILENAME,
43 offsetof(rlm_policy_t,filename), NULL, "${confdir}/policy.txt"},
45 { NULL, -1, 0, NULL, NULL } /* end the list */
50 * Callbacks for red-black trees.
52 static int policyname_cmp(const void *a, const void *b)
54 return strcmp(((const policy_named_t *)a)->name,
55 ((const policy_named_t *)b)->name);
62 static int policy_detach(void *instance)
64 rlm_policy_t *inst = instance;
66 if (inst->policies) rbtree_free(inst->policies);
72 * Do any per-module initialization that is separate to each
73 * configured instance of the module. e.g. set up connections
74 * to external databases, read configuration files, set up
75 * dictionary entries, etc.
77 * If configuration information is given in the config section
78 * that must be referenced in later calls, store a handle to it
79 * in *instance otherwise put a null pointer there.
81 static int policy_instantiate(CONF_SECTION *conf, void **instance)
86 * Set up a storage area for instance data
88 inst = rad_malloc(sizeof(*inst));
92 memset(inst, 0, sizeof(*inst));
95 * If the configuration parameters can't be parsed, then
98 if (cf_section_parse(conf, inst, module_config) < 0) {
103 inst->policies = rbtree_create(policyname_cmp,
104 (void (*)(void *)) rlm_policy_free_item,
106 if (!inst->policies) {
112 * Parse the policy from the file.
114 if (!rlm_policy_parse(inst->policies, inst->filename)) {
126 * Insert a named policy into a list.
128 int rlm_policy_insert(rbtree_t *head, policy_named_t *policy)
130 if (!rbtree_insert(head, policy)) {
139 * Find a named policy
141 policy_named_t *rlm_policy_find(rbtree_t *head, const char *name)
143 policy_named_t mypolicy;
145 mypolicy.name = name;
147 return rbtree_finddata(head, &mypolicy);
152 * Find the named user in this modules database. Create the set
153 * of attribute-value pairs to check and reply with for this user
154 * from the database. The authentication code only needs to check
155 * the password, the rest is done here.
157 static int policy_authorize(void *instance, REQUEST *request)
159 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
164 static int policy_preacct(void *instance, REQUEST *request)
166 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
170 static int policy_accounting(void *instance, REQUEST *request)
172 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
176 static int policy_post_auth(void *instance, REQUEST *request)
178 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
182 static int policy_pre_proxy(void *instance, REQUEST *request)
184 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
188 static int policy_post_proxy(void *instance, REQUEST *request)
190 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
195 static int policy_recv_coa(void *instance, REQUEST *request)
197 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
200 static int policy_send_coa(void *instance, REQUEST *request)
202 return rlm_policy_evaluate((rlm_policy_t *) instance, request,
208 * The "free" functions are here, for no particular reason.
210 void rlm_policy_free_item(policy_item_t *item)
213 policy_item_t *next = item->next;
215 switch (item->type) {
217 case POLICY_TYPE_BAD:
220 case POLICY_TYPE_ASSIGNMENT:
222 policy_assignment_t *this;
224 this = (policy_assignment_t *) item;
225 if (this->lhs) free(this->lhs);
226 if (this->rhs) free(this->rhs);
230 case POLICY_TYPE_CONDITIONAL:
232 policy_condition_t *this;
234 this = (policy_condition_t *) item;
235 if (this->lhs) free(this->lhs);
236 if (this->rhs) free(this->rhs);
239 rlm_policy_free_item(this->child);
249 this = (policy_if_t *) item;
250 if (this->condition) {
251 rlm_policy_free_item(this->condition);
252 this->condition = NULL;
255 rlm_policy_free_item(this->if_true);
256 this->if_true = NULL;
258 if (this->if_false) {
259 rlm_policy_free_item(this->if_false);
260 this->if_false = NULL;
265 case POLICY_TYPE_ATTRIBUTE_LIST:
267 policy_attributes_t *this;
269 this = (policy_attributes_t *) item;
270 rlm_policy_free_item(this->attributes);
274 case POLICY_TYPE_NAMED_POLICY:
276 policy_named_t *this;
278 this = (policy_named_t *) item;
279 rad_assert(this->name != NULL);
280 free((void *) this->name);
281 rlm_policy_free_item(this->policy);
285 case POLICY_TYPE_CALL:
289 this = (policy_call_t *) item;
290 free((void *) this->name);
294 case POLICY_TYPE_RETURN:
295 break; /* do nothing */
297 case POLICY_TYPE_MODULE:
299 policy_module_t *this;
301 this = (policy_module_t *) item;
302 if (this->cs) cf_section_free(&this->cs);
303 if (this->mc) modcallable_free(&this->mc);
306 } /* switch over type */
307 item->next = NULL; /* for debugging & sanity checks */
308 item->type = POLICY_TYPE_BAD;
317 * The module name should be the only globally exported symbol.
318 * That is, everything else should be 'static'.
320 * If the module needs to temporarily modify it's instantiation
321 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
322 * The server will then take care of ensuring that the module
323 * is single-threaded.
325 module_t rlm_policy = {
328 RLM_TYPE_CHECK_CONFIG_SAFE | RLM_TYPE_HUP_SAFE, /* type */
329 policy_instantiate, /* instantiation */
330 policy_detach, /* detach */
332 NULL, /* authentication */
333 policy_authorize, /* authorization */
334 policy_preacct, /* preaccounting */
335 policy_accounting, /* accounting */
336 NULL, /* checksimul */
337 policy_pre_proxy, /* pre-proxy */
338 policy_post_proxy, /* post-proxy */
339 policy_post_auth /* post-auth */