The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_files.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 6e7db7083f93277371155493b53cd8194761d6a2 $
19 * @file rlm_files.c
20 * @brief Process simple 'users' policy files.
21 *
22 * @copyright 2000,2006 The FreeRADIUS server project
23 * @copyright 2000 Jeff Carneal (jeff@apex.net)
24 */
25RCSID("$Id: 6e7db7083f93277371155493b53cd8194761d6a2 $")
26
27#include <freeradius-devel/server/base.h>
28#include <freeradius-devel/server/module_rlm.h>
29#include <freeradius-devel/server/pairmove.h>
30#include <freeradius-devel/server/users_file.h>
31#include <freeradius-devel/util/htrie.h>
32#include <freeradius-devel/unlang/call_env.h>
33#include <freeradius-devel/unlang/function.h>
34#include <freeradius-devel/unlang/transaction.h>
35
36#include <ctype.h>
37#include <fcntl.h>
38
39typedef struct {
40 char const *filename;
43
44/** Structure produced by custom call_env parser
45 */
46typedef struct {
47 tmpl_t *key_tmpl; //!< tmpl used to evaluate lookup key.
48 fr_htrie_t *htrie; //!< parsed files "user" data.
49 PAIR_LIST_LIST *def; //!< parsed files DEFAULT data.
51
52/** Call_env structure
53 */
54typedef struct {
55 rlm_files_data_t *data; //!< Data from parsed call_env.
56 tmpl_t *match_attr; //!< Attribute to populate with matched key value.
57 char const *name; //!< Name of module instance - for debug output.
58 fr_value_box_list_t values; //!< Where the expanded tmpl value will be written.
60
62
65 { .out = &dict_freeradius, .proto = "freeradius" },
66 { NULL }
67};
68
71
74 { .out = &attr_fall_through, .name = "Fall-Through", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
75 { .out = &attr_next_shortest_prefix, .name = "Next-Shortest-Prefix", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
76
77 { NULL }
78};
79
80static const conf_parser_t module_config[] = {
82 { FR_CONF_OFFSET("v3_compat", rlm_files_t, v3_compat) },
84};
85
86
87static uint32_t pairlist_hash(void const *a)
88{
89 return fr_value_box_hash(((PAIR_LIST_LIST const *)a)->box);
90}
91
92static int8_t pairlist_cmp(void const *a, void const *b)
93{
94 int ret;
95
96 ret = fr_value_box_cmp(((PAIR_LIST_LIST const *)a)->box, ((PAIR_LIST_LIST const *)b)->box);
97 return CMP(ret, 0);
98}
99
100static int pairlist_to_key(uint8_t **out, size_t *outlen, void const *a)
101{
102 return fr_value_box_to_key(out, outlen, ((PAIR_LIST_LIST const *)a)->box);
103}
104
105static int getrecv_filename(TALLOC_CTX *ctx, char const *filename, fr_htrie_t **ptree, PAIR_LIST_LIST **pdefault,
106 fr_type_t data_type, fr_dict_attr_t const *key_enum, fr_dict_t const *dict, bool v3_compat)
107{
108 int rcode;
109 PAIR_LIST_LIST users;
110 PAIR_LIST_LIST search_list; // Temporary list header used for matching in htrie
111 PAIR_LIST *entry, *next;
112 PAIR_LIST_LIST *user_list, *default_list;
113 fr_htrie_t *tree;
114 fr_htrie_type_t htype;
115 fr_value_box_t *box;
116 map_t *reply_head;
117
118 if (!filename) {
119 *ptree = NULL;
120 return 0;
121 }
122
123 pairlist_list_init(&users);
124 rcode = pairlist_read(ctx, dict, filename, &users, v3_compat);
125 if (rcode < 0) {
126 return -1;
127 }
128
129 htype = fr_htrie_hint(data_type);
130
131 /*
132 * Walk through the 'users' file list
133 */
134 entry = NULL;
135 while ((entry = fr_dlist_next(&users.head, entry))) {
136 map_t *map = NULL;
137 map_t *prev, *next_map;
138 fr_dict_attr_t const *da;
139 map_t *sub_head, *set_head;
140
141 reply_head = NULL;
142
143 /*
144 * Do various sanity checks.
145 */
146 while ((map = map_list_next(&entry->check, map))) {
147 if (!tmpl_is_attr(map->lhs)) {
148 ERROR("%s[%d] Left side of check item %s is not an attribute",
149 entry->filename, entry->lineno, map->lhs->name);
150 return -1;
151 }
152
153 /*
154 * Disallow regexes for now.
155 */
156 if ((map->op == T_OP_REG_EQ) || (map->op == T_OP_REG_NE)) {
158 }
159
160 /*
161 * Move assignment operations to the reply list.
162 */
163 switch (map->op) {
164 case T_OP_EQ:
165 case T_OP_SET:
166 case T_OP_ADD_EQ:
167 prev = map_list_remove(&entry->check, map);
168 map_list_insert_after(&entry->reply, reply_head, map);
169 reply_head = map;
170 map = prev;
171 break;
172
173 default:
174 break;
175 }
176 } /* end of loop over check items */
177
178 /*
179 * Note that we also re-arrange any control items which are in the reply item list.
180 */
181 sub_head = set_head = NULL;
182
183 /*
184 * Look for server configuration items
185 * in the reply list.
186 *
187 * It's a common enough mistake, that it's
188 * worth doing.
189 */
190 for (map = map_list_head(&entry->reply);
191 map != NULL;
192 map = next_map) {
193 next_map = map_list_next(&entry->reply, map);
194 if (!tmpl_is_attr(map->lhs)) {
195 ERROR("%s[%d] Left side of reply item %s is not an attribute",
196 entry->filename, entry->lineno, map->lhs->name);
197 return -1;
198 }
199 da = tmpl_attr_tail_da(map->lhs);
200
201 if (fr_comparison_op[map->op] && (map->op != T_OP_LE) && (map->op != T_OP_GE)) {
202 ERROR("%s[%d] Invalid operator reply item %s %s ...",
203 entry->filename, entry->lineno, map->lhs->name, fr_tokens[map->op]);
204 return -1;
205 }
206
207 /*
208 * Regex assignments aren't allowed.
209 *
210 * Execs are being deprecated.
211 */
212 if (tmpl_contains_regex(map->rhs) || tmpl_is_exec(map->rhs)) {
213 ERROR("%s[%d] Invalid right-hand side of assignment for attribute %s",
214 entry->filename, entry->lineno, da->name);
215 return -1;
216 }
217
218 if (da == attr_next_shortest_prefix) {
219 if (htype != FR_HTRIE_TRIE) {
220 ERROR("%s[%d] Cannot use %s when key is not an IP / IP prefix",
221 entry->filename, entry->lineno, da->name);
222 return -1;
223 }
224
225 if (!tmpl_is_data(map->rhs) || (tmpl_value_type(map->rhs) != FR_TYPE_BOOL)) {
226 ERROR("%s[%d] Value for %s must be static boolean",
227 entry->filename, entry->lineno, da->name);
228 return -1;
229 }
230
231 entry->next_shortest_prefix = tmpl_value(map->rhs)->vb_bool;
232 (void) map_list_remove(&entry->reply, map);
233 continue;
234 }
235
236 /*
237 * Check for Fall-Through in the reply list. If so, delete it and set the flag
238 * in the entry.
239 *
240 * Note that we don't free "map", as the map functions usually make the "next"
241 * map be talloc parented from the current one. So freeing this one will likely
242 * free all subsequent maps.
243 */
244 if (da == attr_fall_through) {
245 if (!tmpl_is_data(map->rhs) || (tmpl_value_type(map->rhs) != FR_TYPE_BOOL)) {
246 ERROR("%s[%d] Value for %s must be static boolean",
247 entry->filename, entry->lineno, da->name);
248 return -1;
249 }
250
251 entry->fall_through = tmpl_value(map->rhs)->vb_bool;
252 (void) map_list_remove(&entry->reply, map);
253 continue;
254 }
255
256 /*
257 * Removals are applied before anything else.
258 */
259 if (map->op == T_OP_SUB_EQ) {
260 if (sub_head == map) continue;
261
262 (void) map_list_remove(&entry->reply, map);
263 map_list_insert_after(&entry->reply, sub_head, map);
264 sub_head = map;
265 continue;
266 }
267
268 /*
269 * Over-rides are applied after deletions.
270 */
271 if (map->op == T_OP_SET) {
272 if (set_head == map) continue;
273
274 if (!set_head) set_head = sub_head;
275
276 (void) map_list_remove(&entry->reply, map);
277 map_list_insert_after(&entry->reply, set_head, map);
278 set_head = map;
279 continue;
280 }
281 }
282 }
283
284 tree = fr_htrie_alloc(ctx, htype, pairlist_hash, pairlist_cmp, pairlist_to_key, NULL);
285 if (!tree) {
286 while ((entry = fr_dlist_pop_head(&users.head))) {
287 talloc_free(entry);
288 }
289 return -1;
290 }
291
292 default_list = NULL;
293 MEM(box = fr_value_box_alloc(ctx, data_type, NULL));
294
295 /*
296 * We've read the entries in linearly, but putting them
297 * into an indexed data structure would be much faster.
298 * Let's go fix that now.
299 */
300 for (entry = fr_dlist_head(&users.head); entry != NULL; entry = next) {
301 /*
302 * Remove this entry from the input list.
303 */
304 next = fr_dlist_next(&users.head, entry);
305 fr_dlist_remove(&users.head, entry);
306
307 /*
308 * @todo - loop over entry->reply, calling
309 * unlang_fixup_update() or unlang_fixup_filter()
310 * to double-check the maps.
311 *
312 * Those functions do normalization and sanity
313 * checks which are needed if this module is
314 * going to call an unlang function to *apply*
315 * the maps.
316 */
317
318 /*
319 * DEFAULT entries get their own list.
320 */
321 if (strcmp(entry->name, "DEFAULT") == 0) {
322 if (!default_list) {
323 default_list = talloc_zero(ctx, PAIR_LIST_LIST);
324 pairlist_list_init(default_list);
325 default_list->name = entry->name;
326
327 /*
328 * Don't insert the DEFAULT list
329 * into the tree, instead make it
330 * it's own list.
331 */
332 *pdefault = default_list;
333 }
334
335 /*
336 * Append the entry to the DEFAULT list
337 */
338 fr_dlist_insert_tail(&default_list->head, entry);
339 continue;
340 }
341
342 /*
343 * Not DEFAULT, must be a normal user. First look
344 * for a matching list header already in the tree.
345 */
346 search_list.name = entry->name;
347 search_list.box = box;
348
349 /*
350 * Has to be of the correct data type.
351 */
352 if (fr_value_box_from_str(box, box, data_type, key_enum,
353 entry->name, strlen(entry->name), NULL, false) < 0) {
354 ERROR("%s[%d] Failed parsing key %s - %s",
355 entry->filename, entry->lineno, entry->name, fr_strerror());
356 goto error;
357 }
358
359 /*
360 * Find an exact match, especially for patricia tries.
361 */
362 user_list = fr_htrie_match(tree, &search_list);
363 if (!user_list) {
364 user_list = talloc_zero(ctx, PAIR_LIST_LIST);
365 pairlist_list_init(user_list);
366 user_list->name = entry->name;
367 user_list->box = fr_value_box_alloc(user_list, data_type, NULL);
368
369 (void) fr_value_box_copy(user_list, user_list->box, box);
370
371 /*
372 * Insert the new list header.
373 */
374 if (!fr_htrie_insert(tree, user_list)) {
375 ERROR("%s[%d] Failed inserting key %s - %s",
376 entry->filename, entry->lineno, entry->name, fr_strerror());
377 goto error;
378
379 error:
381 talloc_free(tree);
382 return -1;
383 }
384 }
386
387 /*
388 * Append the entry to the user list
389 */
390 fr_dlist_insert_tail(&user_list->head, entry);
391 }
392
393 *ptree = tree;
394
395 return 0;
396}
397
398/** Lookup the expanded key value in files data.
399 *
400 */
401static unlang_action_t CC_HINT(nonnull) mod_files_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
402{
403 rlm_files_env_t *env = talloc_get_type_abort(uctx, rlm_files_env_t);
404 PAIR_LIST_LIST const *user_list;
405 PAIR_LIST const *user_pl, *default_pl;
406 bool found = false, trie = false;
407 PAIR_LIST_LIST my_list;
408 uint8_t key_buffer[16], *key;
409 size_t keylen = 0;
410 fr_edit_list_t *el, *child;
411 fr_htrie_t *tree = env->data->htrie;
412 PAIR_LIST_LIST *default_list = env->data->def;
413 fr_value_box_t *key_vb = fr_value_box_list_head(&env->values);
414
415 if (!key_vb) {
416 RERROR("Missing key value");
418 }
419
420 if (!tree && !default_list) RETURN_MODULE_NOOP;
421
422 RDEBUG2("%s - Looking for key \"%pV\"", env->name, key_vb);
423
425 MEM(child = fr_edit_list_alloc(request, 50, el));
426
427 if (tree) {
428 my_list.name = NULL;
429 my_list.box = key_vb;
430 user_list = fr_htrie_find(tree, &my_list);
431
432 trie = (tree->type == FR_HTRIE_TRIE);
433
434 /*
435 * Convert the value-box to a key for use in a trie. The trie assumes that the key
436 * starts at the high bit of the data, and that isn't always the case. e.g. "bool" and
437 * "integer" may be in host byte order, in which case we have to convert them to network
438 * byte order.
439 */
440 if (user_list && trie) {
441 key = key_buffer;
442 keylen = sizeof(key_buffer) * 8;
443
444 (void) fr_value_box_to_key(&key, &keylen, key_vb);
445
446 RDEBUG3("Keylen %ld", keylen);
447 RHEXDUMP3(key, (keylen + 7) >> 3, "KEY ");
448 }
449
450 user_pl = user_list ? fr_dlist_head(&user_list->head) : NULL;
451 } else {
452 user_pl = NULL;
453 user_list = NULL;
454 }
455
456redo:
457 default_pl = default_list ? fr_dlist_head(&default_list->head) : NULL;
458
459 /*
460 * Find the entry for the user.
461 */
462 while (user_pl || default_pl) {
463 map_t *map = NULL;
464 PAIR_LIST const *pl;
465 bool match = true;
466
467 /*
468 * Figure out which entry to match on.
469 */
470 if (!default_pl && user_pl) {
471 pl = user_pl;
472
473 RDEBUG3("DEFAULT[] USER[%d]=%s", user_pl->lineno, user_pl->name);
474 user_pl = fr_dlist_next(&user_list->head, user_pl);
475
476 } else if (!user_pl && default_pl) {
477 pl = default_pl;
478 RDEBUG3("DEFAULT[%d]= USER[]=", default_pl->lineno);
479 default_pl = fr_dlist_next(&default_list->head, default_pl);
480
481 } else if (user_pl->order < default_pl->order) {
482 pl = user_pl;
483
484 RDEBUG3("DEFAULT[%d]= USER[%d]=%s (choosing user)", default_pl->lineno, user_pl->lineno, user_pl->name);
485 user_pl = fr_dlist_next(&user_list->head, user_pl);
486
487 } else {
488 pl = default_pl;
489 RDEBUG3("DEFAULT[%d]= USER[%d]=%s (choosing default)", default_pl->lineno, user_pl->lineno, user_pl->name);
490 default_pl = fr_dlist_next(&default_list->head, default_pl);
491 }
492
493 /*
494 * Run the check items.
495 */
496 while ((map = map_list_next(&pl->check, map))) {
497 int rcode;
498
499 RDEBUG3(" %s %s %s", map->lhs->name, fr_tokens[map->op], map->rhs ? map->rhs->name : "{ ... }");
500
501 /*
502 * Control items get realized to VPs, and
503 * copied to a temporary list, which is
504 * then copied to control if the entire
505 * line matches.
506 */
507 switch (map->op) {
508 case T_OP_EQ:
509 case T_OP_SET:
510 case T_OP_ADD_EQ:
511 fr_assert(0);
512 goto fail;
513
514 /*
515 * Evaluate the map, including regexes.
516 */
517 default:
518 rcode = radius_legacy_map_cmp(request, map);
519 if (rcode < 0) {
520 RPWARN("Failed parsing map for check item %s, skipping it", map->lhs->name);
521 fail:
522 fr_edit_list_abort(child);
524 }
525
526 if (!rcode) {
527 RDEBUG3(" failed match");
528 match = false;
529 }
530 break;
531 }
532
533 if (!match) break;
534 }
535
536 if (!match) continue;
537
538 RDEBUG2("%s - Found match \"%s\" on line %d of %s", env->name, pl->name, pl->lineno, pl->filename);
539 found = true;
540
541 /*
542 * If match_attr is configured, populate the requested attribute with the
543 * key value from the matching line.
544 */
545 if (env->match_attr) {
546 tmpl_t match_rhs;
547 map_t match_map;
548
549 match_map = (map_t) {
550 .lhs = env->match_attr,
551 .op = T_OP_SET,
552 .rhs = &match_rhs
553 };
554
555 tmpl_init_shallow(&match_rhs, TMPL_TYPE_DATA, T_BARE_WORD, "", 0, NULL);
556 fr_value_box_bstrndup_shallow(&match_map.rhs->data.literal, NULL, pl->name,
557 talloc_array_length(pl->name) - 1, false);
558 if (map_to_request(request, &match_map, map_to_vp, NULL) < 0) {
559 RWARN("Failed populating %s with key value %s", env->match_attr->name, pl->name);
560 }
561 }
562
563 if (map_list_num_elements(&pl->reply) > 0) {
564 RDEBUG2("%s - Preparing attribute updates:", env->name);
565 /* ctx may be reply */
566 RINDENT();
567 if (radius_legacy_map_list_apply(request, &pl->reply, child) < 0) {
568 RPWARN("Failed parsing reply item");
569 REXDENT();
570 goto fail;
571 }
572 REXDENT();
573 }
574
575 if (pl->fall_through) continue;
576
577 /*
578 * We're not doing patricia tries. Stop now.
579 */
580 if (!trie) break;
581
582 /*
583 * We're doing patricia tries, but we've been
584 * told to not walk back up the trie, OR we're at the top of the tree. Stop.
585 */
586 if (!pl->next_shortest_prefix || (keylen == 0)) break;
587
588 /*
589 * Walk back up the trie looking for shorter prefixes.
590 *
591 * Note that we've already found an entry, so we
592 * MUST start with that prefix, otherwise we
593 * would end up in an loop of finding the same
594 * prefix over and over.
595 */
596 if (keylen > user_list->box->vb_ip.prefix) keylen = user_list->box->vb_ip.prefix;
597
598 do {
599 keylen--;
600 user_list = fr_trie_lookup_by_key(tree->store, key, keylen);
601 if (!user_list) {
602 user_pl = NULL;
603 continue;
604 }
605
606 user_pl = fr_dlist_head(&user_list->head);
607 RDEBUG("%s - Found matching shorter subnet %s at key length %ld", env->name, user_pl->name, keylen);
608 goto redo;
609 } while (keylen > 0);
610 }
611
612 /*
613 * See if we succeeded.
614 */
615 if (!found) {
616 fr_edit_list_abort(child);
617 RETURN_MODULE_NOOP; /* on to the next module */
618 }
619
620 fr_edit_list_commit(child);
622}
623
624/** Initiate a files data lookup
625 *
626 * The results of call_env parsing are a structure containing the
627 * tmpl_t representing the key and the parsed files data, meaning tmpl
628 * expansion does not happen by default.
629 * First we push the tmpl onto the stack for evaluation, then the lookup
630 * is done in mod_files_resume.
631 */
632static unlang_action_t CC_HINT(nonnull) mod_files(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
633{
634 rlm_files_env_t *env = talloc_get_type_abort(mctx->env_data, rlm_files_env_t);
635
636 fr_value_box_list_init(&env->values);
637 env->name = mctx->mi->name;
638
639 /*
640 * Set mod_files_resume as the repeat function
641 */
642 if (unlang_function_push(request, NULL, mod_files_resume, NULL, 0, UNLANG_SUB_FRAME, env) < 0) RETURN_MODULE_FAIL;
643
644 /*
645 * Push evaluation of the key tmpl onto the stack
646 */
647 if (unlang_tmpl_push(env, &env->values, request, env->data->key_tmpl, NULL) < 0) RETURN_MODULE_FAIL;
649}
650
651/** Custom call_env parser for loading files data
652 *
653 */
654static int call_env_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
655 call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
656{
658 CONF_PAIR const *to_parse = cf_item_to_pair(ci);
659 rlm_files_data_t *files_data;
660 fr_type_t keytype;
661 fr_dict_attr_t const *key_enum = NULL;
662
663 MEM(files_data = talloc_zero(ctx, rlm_files_data_t));
664
665 if (tmpl_afrom_substr(ctx, &files_data->key_tmpl,
666 &FR_SBUFF_IN(cf_pair_value(to_parse), talloc_array_length(cf_pair_value(to_parse)) - 1),
668 t_rules) < 0) return -1;
669
670 keytype = tmpl_expanded_type(files_data->key_tmpl);
671 if (fr_htrie_hint(keytype) == FR_HTRIE_INVALID) {
672 cf_log_err(ci, "Invalid data type '%s' for 'files' module", fr_type_to_str(keytype));
673 error:
674 talloc_free(files_data);
675 return -1;
676 }
677
678 if (files_data->key_tmpl->type == TMPL_TYPE_ATTR) {
679 key_enum = tmpl_attr_tail_da(files_data->key_tmpl);
680 }
681
682 if (getrecv_filename(files_data, inst->filename, &files_data->htrie, &files_data->def,
683 keytype, key_enum, t_rules->attr.dict_def, inst->v3_compat) < 0) goto error;
684
685 *(void **)out = files_data;
686 return 0;
687}
688
691 .env = (call_env_parser_t[]){
693 .pair.dflt = "%{%{Stripped-User-Name} || %{User-Name}}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING,
694 .pair.func = call_env_parse },
697 },
698};
699
700/* globally exported name */
703 .common = {
704 .magic = MODULE_MAGIC_INIT,
705 .name = "files",
706 .inst_size = sizeof(rlm_files_t),
708 },
709 .method_group = {
710 .bindings = (module_method_binding_t[]){
711 { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_files, .method_env = &method_env },
713 }
714 }
715};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:39
#define RCSID(id)
Definition build.h:483
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define UNUSED
Definition build.h:315
#define CALL_ENV_TERMINATOR
Definition call_env.h:236
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
Definition call_env.h:240
call_env_parser_t const * env
Parsing rules for call method env.
Definition call_env.h:247
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl MUST contain an attribute reference.
Definition call_env.h:86
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
Definition call_env.h:85
module_instance_t const * mi
Module instance that the callenv is registered to.
Definition call_env.h:229
#define FR_CALL_ENV_PARSE_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _parse_field)
Specify a call_env_parser_t which writes out the result of the parsing phase to the field specified.
Definition call_env.h:389
Per method call config.
Definition call_env.h:180
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:658
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:284
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:272
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:434
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition cf_parse.h:440
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:595
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1638
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:664
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define CF_IDENT_ANY
Definition cf_util.h:78
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
Definition dlist.h:486
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition dlist.h:638
static void * fr_dlist_pop_head(fr_dlist_head_t *list_head)
Remove the head item in a list.
Definition dlist.h:672
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition dlist.h:378
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition dlist.h:555
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:111
fr_htrie_t * fr_htrie_alloc(TALLOC_CTX *ctx, fr_htrie_type_t type, fr_hash_t hash_data, fr_cmp_t cmp_data, fr_trie_key_t get_key, fr_free_t free_data)
An abstraction over our internal hashes, rb trees, and prefix tries.
Definition htrie.c:92
fr_htrie_type_t
Definition htrie.h:49
@ FR_HTRIE_TRIE
Data is stored in a prefix trie.
Definition htrie.h:53
@ FR_HTRIE_INVALID
Definition htrie.h:50
static fr_htrie_type_t fr_htrie_hint(fr_type_t type)
Definition htrie.h:149
static bool fr_htrie_insert(fr_htrie_t *ht, void const *data)
Insert data into a htrie.
Definition htrie.h:112
static void * fr_htrie_match(fr_htrie_t *ht, void const *data)
Match data in a htrie.
Definition htrie.h:96
void * store
What we're using to store node data.
Definition htrie.h:82
fr_htrie_type_t type
type of the htrie
Definition htrie.h:81
static void * fr_htrie_find(fr_htrie_t *ht, void const *data)
Find data in a htrie.
Definition htrie.h:104
A hash/rb/prefix trie abstraction.
Definition htrie.h:80
#define UNLANG_SUB_FRAME
Definition interpret.h:36
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:443
#define RDEBUG3(fmt,...)
Definition log.h:343
#define RWARN(fmt,...)
Definition log.h:297
#define RERROR(fmt,...)
Definition log.h:298
#define RPWARN(fmt,...)
Definition log.h:301
#define RHEXDUMP3(_data, _len, _fmt,...)
Definition log.h:705
#define RINDENT()
Indent R* messages by one level.
Definition log.h:430
int map_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, UNUSED void *uctx)
Convert a map to a fr_pair_t.
Definition map.c:1562
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
Definition map.c:1856
talloc_free(reap)
struct map_s map_t
Definition map.h:33
fr_type_t
@ FR_TYPE_VOID
User data.
@ FR_TYPE_BOOL
A truth value.
unsigned int uint32_t
unsigned char uint8_t
void * env_data
Per call environment data.
Definition module_ctx.h:44
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
int radius_legacy_map_cmp(request_t *request, map_t const *map)
Definition pairmove.c:790
int radius_legacy_map_list_apply(request_t *request, map_list_t const *list, fr_edit_list_t *el)
Definition pairmove.c:771
static const conf_parser_t config[]
Definition base.c:183
#define fr_assert(_expr)
Definition rad_assert.h:38
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define RDEBUG(fmt,...)
Definition radclient.h:53
#define RETURN_MODULE_NOOP
Definition rcode.h:62
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
fr_dict_attr_autoload_t rlm_files_dict_attr[]
Definition rlm_files.c:73
static int pairlist_to_key(uint8_t **out, size_t *outlen, void const *a)
Definition rlm_files.c:100
char const * filename
Definition rlm_files.c:40
static unlang_action_t mod_files_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Lookup the expanded key value in files data.
Definition rlm_files.c:401
PAIR_LIST_LIST * def
parsed files DEFAULT data.
Definition rlm_files.c:49
static int8_t pairlist_cmp(void const *a, void const *b)
Definition rlm_files.c:92
static const call_env_method_t method_env
Definition rlm_files.c:689
static fr_dict_attr_t const * attr_fall_through
Definition rlm_files.c:69
static fr_dict_t const * dict_freeradius
Definition rlm_files.c:61
fr_htrie_t * htrie
parsed files "user" data.
Definition rlm_files.c:48
static int call_env_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
Custom call_env parser for loading files data.
Definition rlm_files.c:654
static unlang_action_t mod_files(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Initiate a files data lookup.
Definition rlm_files.c:632
tmpl_t * match_attr
Attribute to populate with matched key value.
Definition rlm_files.c:56
static int getrecv_filename(TALLOC_CTX *ctx, char const *filename, fr_htrie_t **ptree, PAIR_LIST_LIST **pdefault, fr_type_t data_type, fr_dict_attr_t const *key_enum, fr_dict_t const *dict, bool v3_compat)
Definition rlm_files.c:105
static uint32_t pairlist_hash(void const *a)
Definition rlm_files.c:87
fr_dict_autoload_t rlm_files_dict[]
Definition rlm_files.c:64
tmpl_t * key_tmpl
tmpl used to evaluate lookup key.
Definition rlm_files.c:47
rlm_files_data_t * data
Data from parsed call_env.
Definition rlm_files.c:55
static fr_dict_attr_t const * attr_next_shortest_prefix
Definition rlm_files.c:70
char const * name
Name of module instance - for debug output.
Definition rlm_files.c:57
fr_value_box_list_t values
Where the expanded tmpl value will be written.
Definition rlm_files.c:58
static const conf_parser_t module_config[]
Definition rlm_files.c:80
module_rlm_t rlm_files
Definition rlm_files.c:702
bool v3_compat
Definition rlm_files.c:41
Structure produced by custom call_env parser.
Definition rlm_files.c:46
Call_env structure.
Definition rlm_files.c:54
#define FR_SBUFF_IN(_start, _len_or_end)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
char const * name
Instance name e.g. user_database.
Definition module.h:335
size_t inst_size
Size of the module's instance data.
Definition module.h:203
void * data
Module's instance data.
Definition module.h:271
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:151
Named methods exported by a module.
Definition module.h:173
#define tmpl_value(_tmpl)
Definition tmpl.h:954
#define tmpl_contains_regex(vpt)
Definition tmpl.h:231
#define tmpl_is_attr(vpt)
Definition tmpl.h:213
#define tmpl_is_exec(vpt)
Definition tmpl.h:216
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:146
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:142
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
#define tmpl_is_data(vpt)
Definition tmpl.h:211
#define tmpl_value_type(_tmpl)
Definition tmpl.h:956
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:350
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:818
#define tmpl_is_regex(vpt)
Definition tmpl.h:218
tmpl_t * tmpl_init_shallow(tmpl_t *vpt, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len, tmpl_rules_t const *t_rules))
Initialise a tmpl without copying the input name string.
fr_type_t tmpl_expanded_type(tmpl_t const *vpt)
Return the native data type of the expression.
Definition tmpl_eval.c:209
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:347
eap_aka_sim_process_conf_t * inst
Value pair map.
Definition map.h:77
fr_token_t op
The operator that controls insertion of the dst attribute.
Definition map.h:82
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
Definition map.h:78
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Definition map.h:79
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:287
#define talloc_get_type_abort_const
Definition talloc.h:282
int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args)
Push a tmpl onto the stack for evaluation.
Definition tmpl.c:262
char const * fr_tokens[T_TOKEN_LAST]
Definition token.c:78
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:198
@ T_OP_SUB_EQ
Definition token.h:70
@ T_BARE_WORD
Definition token.h:120
@ T_OP_EQ
Definition token.h:83
@ T_OP_SET
Definition token.h:84
@ T_OP_ADD_EQ
Definition token.h:69
@ T_OP_REG_EQ
Definition token.h:102
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
@ T_OP_LE
Definition token.h:100
@ T_OP_GE
Definition token.h:98
@ T_OP_REG_NE
Definition token.h:103
fr_edit_list_t * unlang_interpret_edit_list(request_t *request)
void * fr_trie_lookup_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Lookup a key in a trie and return user ctx, if any.
Definition trie.c:1262
static fr_event_list_t * el
static int next_map(UNUSED request_t *request, UNUSED unlang_frame_state_edit_t *state, edit_map_t *current)
Definition edit.c:940
int pairlist_read(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR_LIST_LIST *list, bool v3_compat)
Definition users_file.c:235
char const * name
Key for matching entry.
Definition users_file.h:39
fr_dlist_head_t head
Head of the list of PAIR_LISTs.
Definition users_file.h:51
char const * filename
Filename entry read from.
Definition users_file.h:45
int lineno
Line number entry read from.
Definition users_file.h:46
char const * name
name of the key used for matching entry.
Definition users_file.h:52
bool fall_through
go to the next one
Definition users_file.h:43
static void pairlist_list_init(PAIR_LIST_LIST *list)
Definition users_file.h:58
int order
Sequence of entry in source file.
Definition users_file.h:42
map_list_t check
List of maps for comparison / modifying control list.
Definition users_file.h:40
fr_value_box_t * box
parsed version of "name".
Definition users_file.h:53
bool next_shortest_prefix
for prefix tries
Definition users_file.h:44
map_list_t reply
List of maps for modifying reply list.
Definition users_file.h:41
void fr_edit_list_commit(fr_edit_list_t *el)
Commit an edit list.
Definition edit.c:841
void fr_edit_list_abort(fr_edit_list_t *el)
Abort the entries in an edit list.
Definition edit.c:194
fr_edit_list_t * fr_edit_list_alloc(TALLOC_CTX *ctx, int hint, fr_edit_list_t *parent)
Allocate an edit list.
Definition edit.c:790
Track a series of edits.
Definition edit.c:102
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
Definition value.c:5361
uint32_t fr_value_box_hash(fr_value_box_t const *vb)
Hash the contents of a value box.
Definition value.c:6175
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
Definition value.c:606
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:676
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:3740
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:3681
int fr_value_box_to_key(uint8_t **out, size_t *outlen, fr_value_box_t const *value)
Get a key from a value box.
Definition value.c:2084
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
Definition value.c:4232
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:621
static fr_slen_t data
Definition value.h:1265
int nonnull(2, 5))
static size_t char ** out
Definition value.h:997