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: a0075ab85301fa4b6be36a8d0fa3fa6cc396bc54 $
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: a0075ab85301fa4b6be36a8d0fa3fa6cc396bc54 $")
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;
44
45/** Structure produced by custom call_env parser
46 */
47typedef struct {
48 tmpl_t *key_tmpl; //!< tmpl used to evaluate lookup key.
49 fr_htrie_t *htrie; //!< parsed files "user" data.
50 PAIR_LIST_LIST *def; //!< parsed files DEFAULT data.
52
53/** Call_env structure
54 */
55typedef struct {
56 rlm_files_data_t *data; //!< Data from parsed call_env.
57 tmpl_t *match_attr; //!< Attribute to populate with matched key value.
58 char const *name; //!< Name of module instance - for debug output.
59 fr_value_box_list_t values; //!< Where the expanded tmpl value will be written.
61
63
66 { .out = &dict_freeradius, .proto = "freeradius" },
67 { NULL }
68};
69
72
75 { .out = &attr_fall_through, .name = "Fall-Through", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
76 { .out = &attr_next_shortest_prefix, .name = "Next-Shortest-Prefix", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
77
78 { NULL }
79};
80
81static const conf_parser_t module_config[] = {
83 { FR_CONF_OFFSET("v3_compat", rlm_files_t, v3_compat) },
84 { FR_CONF_OFFSET("lookup_type", rlm_files_t, htype), .dflt = "auto",
87};
88
89
90static uint32_t pairlist_hash(void const *a)
91{
92 return fr_value_box_hash(((PAIR_LIST_LIST const *)a)->box);
93}
94
95static int8_t pairlist_cmp(void const *a, void const *b)
96{
97 int ret;
98
99 ret = fr_value_box_cmp(((PAIR_LIST_LIST const *)a)->box, ((PAIR_LIST_LIST const *)b)->box);
100 return CMP(ret, 0);
101}
102
103static int pairlist_to_key(uint8_t **out, size_t *outlen, void const *a)
104{
105 return fr_value_box_to_key(out, outlen, ((PAIR_LIST_LIST const *)a)->box);
106}
107
108static int getrecv_filename(TALLOC_CTX *ctx, rlm_files_t const *inst, fr_htrie_t **ptree, PAIR_LIST_LIST **pdefault,
109 fr_type_t data_type, fr_dict_attr_t const *key_enum, fr_dict_t const *dict)
110{
111 int rcode;
112 PAIR_LIST_LIST users;
113 PAIR_LIST_LIST search_list; // Temporary list header used for matching in htrie
114 PAIR_LIST *entry, *next;
115 PAIR_LIST_LIST *user_list, *default_list;
116 fr_htrie_t *tree;
117 fr_htrie_type_t htype;
118 fr_value_box_t *box;
119 map_t *reply_head;
120
121 if (!inst->filename) {
122 *ptree = NULL;
123 return 0;
124 }
125
126 pairlist_list_init(&users);
127 rcode = pairlist_read(ctx, dict, inst->filename, &users, inst->v3_compat);
128 if (rcode < 0) {
129 return -1;
130 }
131
132 if (inst->htype == FR_HTRIE_AUTO) {
133 htype = fr_htrie_hint(data_type);
134 } else {
135 htype = inst->htype;
136 }
137
138 /*
139 * Walk through the 'users' file list
140 */
141 entry = NULL;
142 while ((entry = fr_dlist_next(&users.head, entry))) {
143 map_t *map = NULL;
144 map_t *prev, *next_map;
145 fr_dict_attr_t const *da;
146 map_t *sub_head, *set_head;
147
148 reply_head = NULL;
149
150 /*
151 * Do various sanity checks.
152 */
153 while ((map = map_list_next(&entry->check, map))) {
154 if (!tmpl_is_attr(map->lhs)) {
155 ERROR("%s[%d] Left side of check item %s is not an attribute",
156 entry->filename, entry->lineno, map->lhs->name);
157 return -1;
158 }
159
160 /*
161 * Disallow regexes for now.
162 */
163 if ((map->op == T_OP_REG_EQ) || (map->op == T_OP_REG_NE)) {
165 }
166
167 /*
168 * Move assignment operations to the reply list.
169 */
170 switch (map->op) {
171 case T_OP_EQ:
172 case T_OP_SET:
173 case T_OP_ADD_EQ:
174 prev = map_list_remove(&entry->check, map);
175 map_list_insert_after(&entry->reply, reply_head, map);
176 reply_head = map;
177 map = prev;
178 break;
179
180 default:
181 break;
182 }
183 } /* end of loop over check items */
184
185 /*
186 * Note that we also re-arrange any control items which are in the reply item list.
187 */
188 sub_head = set_head = NULL;
189
190 /*
191 * Look for server configuration items
192 * in the reply list.
193 *
194 * It's a common enough mistake, that it's
195 * worth doing.
196 */
197 for (map = map_list_head(&entry->reply);
198 map != NULL;
199 map = next_map) {
200 next_map = map_list_next(&entry->reply, map);
201 if (!tmpl_is_attr(map->lhs)) {
202 ERROR("%s[%d] Left side of reply item %s is not an attribute",
203 entry->filename, entry->lineno, map->lhs->name);
204 return -1;
205 }
206 da = tmpl_attr_tail_da(map->lhs);
207
208 if (fr_comparison_op[map->op] && (map->op != T_OP_LE) && (map->op != T_OP_GE)) {
209 ERROR("%s[%d] Invalid operator reply item %s %s ...",
210 entry->filename, entry->lineno, map->lhs->name, fr_tokens[map->op]);
211 return -1;
212 }
213
214 /*
215 * Regex assignments aren't allowed.
216 *
217 * Execs are being deprecated.
218 */
219 if (tmpl_contains_regex(map->rhs) || tmpl_is_exec(map->rhs)) {
220 ERROR("%s[%d] Invalid right-hand side of assignment for attribute %s",
221 entry->filename, entry->lineno, da->name);
222 return -1;
223 }
224
225 if (da == attr_next_shortest_prefix) {
226 if (htype != FR_HTRIE_TRIE) {
227 ERROR("%s[%d] Cannot use %s when key is not an IP / IP prefix",
228 entry->filename, entry->lineno, da->name);
229 return -1;
230 }
231
232 if (!tmpl_is_data(map->rhs) || (tmpl_value_type(map->rhs) != FR_TYPE_BOOL)) {
233 ERROR("%s[%d] Value for %s must be static boolean",
234 entry->filename, entry->lineno, da->name);
235 return -1;
236 }
237
238 entry->next_shortest_prefix = tmpl_value(map->rhs)->vb_bool;
239 (void) map_list_remove(&entry->reply, map);
240 continue;
241 }
242
243 /*
244 * Check for Fall-Through in the reply list. If so, delete it and set the flag
245 * in the entry.
246 *
247 * Note that we don't free "map", as the map functions usually make the "next"
248 * map be talloc parented from the current one. So freeing this one will likely
249 * free all subsequent maps.
250 */
251 if (da == attr_fall_through) {
252 if (!tmpl_is_data(map->rhs) || (tmpl_value_type(map->rhs) != FR_TYPE_BOOL)) {
253 ERROR("%s[%d] Value for %s must be static boolean",
254 entry->filename, entry->lineno, da->name);
255 return -1;
256 }
257
258 entry->fall_through = tmpl_value(map->rhs)->vb_bool;
259 (void) map_list_remove(&entry->reply, map);
260 continue;
261 }
262
263 /*
264 * Removals are applied before anything else.
265 */
266 if (map->op == T_OP_SUB_EQ) {
267 if (sub_head == map) continue;
268
269 (void) map_list_remove(&entry->reply, map);
270 map_list_insert_after(&entry->reply, sub_head, map);
271 sub_head = map;
272 continue;
273 }
274
275 /*
276 * Over-rides are applied after deletions.
277 */
278 if (map->op == T_OP_SET) {
279 if (set_head == map) continue;
280
281 if (!set_head) set_head = sub_head;
282
283 (void) map_list_remove(&entry->reply, map);
284 map_list_insert_after(&entry->reply, set_head, map);
285 set_head = map;
286 continue;
287 }
288 }
289 }
290
291 tree = fr_htrie_alloc(ctx, htype, pairlist_hash, pairlist_cmp, pairlist_to_key, NULL);
292 if (!tree) {
293 while ((entry = fr_dlist_pop_head(&users.head))) {
294 talloc_free(entry);
295 }
296 return -1;
297 }
298
299 default_list = NULL;
300 MEM(box = fr_value_box_alloc(ctx, data_type, NULL));
301
302 /*
303 * We've read the entries in linearly, but putting them
304 * into an indexed data structure would be much faster.
305 * Let's go fix that now.
306 */
307 for (entry = fr_dlist_head(&users.head); entry != NULL; entry = next) {
308 /*
309 * Remove this entry from the input list.
310 */
311 next = fr_dlist_next(&users.head, entry);
312 fr_dlist_remove(&users.head, entry);
313
314 /*
315 * @todo - loop over entry->reply, calling
316 * unlang_fixup_update() or unlang_fixup_filter()
317 * to double-check the maps.
318 *
319 * Those functions do normalization and sanity
320 * checks which are needed if this module is
321 * going to call an unlang function to *apply*
322 * the maps.
323 */
324
325 /*
326 * DEFAULT entries get their own list.
327 */
328 if (strcmp(entry->name, "DEFAULT") == 0) {
329 if (!default_list) {
330 default_list = talloc_zero(ctx, PAIR_LIST_LIST);
331 pairlist_list_init(default_list);
332 default_list->name = entry->name;
333
334 /*
335 * Don't insert the DEFAULT list
336 * into the tree, instead make it
337 * it's own list.
338 */
339 *pdefault = default_list;
340 }
341
342 /*
343 * Append the entry to the DEFAULT list
344 */
345 fr_dlist_insert_tail(&default_list->head, entry);
346 continue;
347 }
348
349 /*
350 * Not DEFAULT, must be a normal user. First look
351 * for a matching list header already in the tree.
352 */
353 search_list.name = entry->name;
354 search_list.box = box;
355
356 /*
357 * Has to be of the correct data type.
358 */
359 if (fr_value_box_from_str(box, box, data_type, key_enum,
360 entry->name, strlen(entry->name), NULL) < 0) {
361 ERROR("%s[%d] Failed parsing key %s - %s",
362 entry->filename, entry->lineno, entry->name, fr_strerror());
363 goto error;
364 }
365
366 /*
367 * Find an exact match, especially for patricia tries.
368 */
369 user_list = fr_htrie_match(tree, &search_list);
370 if (!user_list) {
371 user_list = talloc_zero(ctx, PAIR_LIST_LIST);
372 pairlist_list_init(user_list);
373 user_list->name = entry->name;
374 user_list->box = fr_value_box_alloc(user_list, data_type, NULL);
375
376 if (unlikely(fr_value_box_copy(user_list, user_list->box, box) < 0)) {
377 PERROR("%s[%d] Failed copying key %s",
378 entry->filename, entry->lineno, entry->name);
379 }
380
381 /*
382 * Insert the new list header.
383 */
384 if (!fr_htrie_insert(tree, user_list)) {
385 PERROR("%s[%d] Failed inserting key %s",
386 entry->filename, entry->lineno, entry->name);
387 goto error;
388
389 error:
391 talloc_free(tree);
392 return -1;
393 }
394 }
396
397 /*
398 * Append the entry to the user list
399 */
400 fr_dlist_insert_tail(&user_list->head, entry);
401 }
402
403 *ptree = tree;
404
405 return 0;
406}
407
408/** Lookup the expanded key value in files data.
409 *
410 */
411static unlang_action_t CC_HINT(nonnull) mod_files_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
412{
413 rlm_files_env_t *env = talloc_get_type_abort(mctx->env_data, rlm_files_env_t);
414 PAIR_LIST_LIST const *user_list;
415 PAIR_LIST const *user_pl, *default_pl;
416 bool found = false, trie = false;
417 PAIR_LIST_LIST my_list;
418 uint8_t key_buffer[16], *key;
419 size_t keylen = 0;
420 fr_edit_list_t *el, *child;
421 fr_htrie_t *tree = env->data->htrie;
422 PAIR_LIST_LIST *default_list = env->data->def;
423 fr_value_box_t *key_vb = fr_value_box_list_head(&env->values);
424
425 if (!key_vb) {
426 RERROR("Missing key value");
428 }
429
430 if (!tree && !default_list) {
432 }
433
434 RDEBUG2("%s - Looking for key \"%pV\"", env->name, key_vb);
435
437 MEM(child = fr_edit_list_alloc(request, 50, el));
438
439 if (tree) {
440 my_list.name = NULL;
441 my_list.box = key_vb;
442 user_list = fr_htrie_find(tree, &my_list);
443
444 trie = (tree->type == FR_HTRIE_TRIE);
445
446 /*
447 * Convert the value-box to a key for use in a trie. The trie assumes that the key
448 * starts at the high bit of the data, and that isn't always the case. e.g. "bool" and
449 * "integer" may be in host byte order, in which case we have to convert them to network
450 * byte order.
451 */
452 if (user_list && trie) {
453 key = key_buffer;
454 keylen = sizeof(key_buffer) * 8;
455
456 (void) fr_value_box_to_key(&key, &keylen, key_vb);
457
458 RDEBUG3("Keylen %ld", keylen);
459 RHEXDUMP3(key, (keylen + 7) >> 3, "KEY ");
460 }
461
462 user_pl = user_list ? fr_dlist_head(&user_list->head) : NULL;
463 } else {
464 user_pl = NULL;
465 user_list = NULL;
466 }
467
468redo:
469 default_pl = default_list ? fr_dlist_head(&default_list->head) : NULL;
470
471 /*
472 * Find the entry for the user.
473 */
474 while (user_pl || default_pl) {
475 map_t *map = NULL;
476 PAIR_LIST const *pl;
477 bool match = true;
478
479 /*
480 * Figure out which entry to match on.
481 */
482 if (!default_pl && user_pl) {
483 pl = user_pl;
484
485 RDEBUG3("DEFAULT[] USER[%d]=%s", user_pl->lineno, user_pl->name);
486 user_pl = fr_dlist_next(&user_list->head, user_pl);
487
488 } else if (!user_pl && default_pl) {
489 pl = default_pl;
490 RDEBUG3("DEFAULT[%d]= USER[]=", default_pl->lineno);
491 default_pl = fr_dlist_next(&default_list->head, default_pl);
492
493 } else if (user_pl->order < default_pl->order) {
494 pl = user_pl;
495
496 RDEBUG3("DEFAULT[%d]= USER[%d]=%s (choosing user)", default_pl->lineno, user_pl->lineno, user_pl->name);
497 user_pl = fr_dlist_next(&user_list->head, user_pl);
498
499 } else {
500 pl = default_pl;
501 RDEBUG3("DEFAULT[%d]= USER[%d]=%s (choosing default)", default_pl->lineno, user_pl->lineno, user_pl->name);
502 default_pl = fr_dlist_next(&default_list->head, default_pl);
503 }
504
505 /*
506 * Run the check items.
507 */
508 while ((map = map_list_next(&pl->check, map))) {
509 int rcode;
510
511 RDEBUG3(" %s %s %s", map->lhs->name, fr_tokens[map->op], map->rhs ? map->rhs->name : "{ ... }");
512
513 /*
514 * Control items get realized to VPs, and
515 * copied to a temporary list, which is
516 * then copied to control if the entire
517 * line matches.
518 */
519 switch (map->op) {
520 case T_OP_EQ:
521 case T_OP_SET:
522 case T_OP_ADD_EQ:
523 fr_assert(0);
524 goto fail;
525
526 /*
527 * Evaluate the map, including regexes.
528 */
529 default:
530 rcode = radius_legacy_map_cmp(request, map);
531 if (rcode < 0) {
532 RPWARN("Failed parsing map for check item %s, skipping it", map->lhs->name);
533 fail:
534 fr_edit_list_abort(child);
536 }
537
538 if (!rcode) {
539 RDEBUG3(" failed match");
540 match = false;
541 }
542 break;
543 }
544
545 if (!match) break;
546 }
547
548 if (!match) continue;
549
550 RDEBUG2("%s - Found match \"%s\" on line %d of %s", env->name, pl->name, pl->lineno, pl->filename);
551 found = true;
552
553 /*
554 * If match_attr is configured, populate the requested attribute with the
555 * key value from the matching line.
556 */
557 if (env->match_attr) {
558 tmpl_t match_rhs;
559 map_t match_map;
560
561 match_map = (map_t) {
562 .lhs = env->match_attr,
563 .op = T_OP_SET,
564 .rhs = &match_rhs
565 };
566
567 tmpl_init_shallow(&match_rhs, TMPL_TYPE_DATA, T_BARE_WORD, "", 0, NULL);
568 fr_value_box_bstrndup_shallow(&match_map.rhs->data.literal, NULL, pl->name,
569 talloc_array_length(pl->name) - 1, false);
570 if (map_to_request(request, &match_map, map_to_vp, NULL) < 0) {
571 RWARN("Failed populating %s with key value %s", env->match_attr->name, pl->name);
572 }
573 }
574
575 if (map_list_num_elements(&pl->reply) > 0) {
576 RDEBUG2("%s - Preparing attribute updates:", env->name);
577 /* ctx may be reply */
578 RINDENT();
579 if (radius_legacy_map_list_apply(request, &pl->reply, child) < 0) {
580 RPWARN("Failed parsing reply item");
581 REXDENT();
582 goto fail;
583 }
584 REXDENT();
585 }
586
587 if (pl->fall_through) continue;
588
589 /*
590 * We're not doing patricia tries. Stop now.
591 */
592 if (!trie) break;
593
594 /*
595 * We're doing patricia tries, but we've been
596 * told to not walk back up the trie, OR we're at the top of the tree. Stop.
597 */
598 if (!pl->next_shortest_prefix || (keylen == 0)) break;
599
600 /*
601 * Walk back up the trie looking for shorter prefixes.
602 *
603 * Note that we've already found an entry, so we
604 * MUST start with that prefix, otherwise we
605 * would end up in an loop of finding the same
606 * prefix over and over.
607 */
608 if (keylen > user_list->box->vb_ip.prefix) keylen = user_list->box->vb_ip.prefix;
609
610 do {
611 keylen--;
612 user_list = fr_trie_lookup_by_key(tree->store, key, keylen);
613 if (!user_list) {
614 user_pl = NULL;
615 continue;
616 }
617
618 user_pl = fr_dlist_head(&user_list->head);
619 RDEBUG("%s - Found matching shorter subnet %s at key length %ld", env->name, user_pl->name, keylen);
620 goto redo;
621 } while (keylen > 0);
622 }
623
624 /*
625 * See if we succeeded.
626 */
627 if (!found) {
628 fr_edit_list_abort(child);
630 }
631
632 fr_edit_list_commit(child);
633
635}
636
637/** Initiate a files data lookup
638 *
639 * The results of call_env parsing are a structure containing the
640 * tmpl_t representing the key and the parsed files data, meaning tmpl
641 * expansion does not happen by default.
642 * First we push the tmpl onto the stack for evaluation, then the lookup
643 * is done in mod_files_resume.
644 */
645static unlang_action_t CC_HINT(nonnull) mod_files(UNUSED unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
646{
647 rlm_files_env_t *env = talloc_get_type_abort(mctx->env_data, rlm_files_env_t);
648
649 fr_value_box_list_init(&env->values);
650 env->name = mctx->mi->name;
651
652 return unlang_module_yield_to_tmpl(env, &env->values, request, env->data->key_tmpl,
653 NULL, mod_files_resume, NULL, 0, NULL);
654}
655
656/** Custom call_env parser for loading files data
657 *
658 */
659static int files_call_env_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
660 call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
661{
663 CONF_PAIR const *to_parse = cf_item_to_pair(ci);
664 rlm_files_data_t *files_data;
665 fr_type_t keytype;
666 fr_dict_attr_t const *key_enum = NULL;
667
668 MEM(files_data = talloc_zero(ctx, rlm_files_data_t));
669
670 if (tmpl_afrom_substr(ctx, &files_data->key_tmpl,
671 &FR_SBUFF_IN(cf_pair_value(to_parse), talloc_array_length(cf_pair_value(to_parse)) - 1),
673 t_rules) < 0) return -1;
674
675 keytype = tmpl_expanded_type(files_data->key_tmpl);
676 if (fr_htrie_hint(keytype) == FR_HTRIE_INVALID) {
677 cf_log_err(ci, "Invalid data type '%s' for 'files' module", fr_type_to_str(keytype));
678 error:
679 talloc_free(files_data);
680 return -1;
681 }
682
683 if (files_data->key_tmpl->type == TMPL_TYPE_ATTR) {
684 key_enum = tmpl_attr_tail_da(files_data->key_tmpl);
685 }
686
687 if (getrecv_filename(files_data, inst, &files_data->htrie, &files_data->def,
688 keytype, key_enum, t_rules->attr.dict_def) < 0) goto error;
689
690 *(void **)out = files_data;
691 return 0;
692}
693
696 .env = (call_env_parser_t[]){
698 .pair.dflt = "%{Stripped-User-Name || User-Name}", .pair.dflt_quote = T_DOUBLE_QUOTED_STRING,
699 .pair.func = files_call_env_parse },
702 },
703};
704
705/* globally exported name */
708 .common = {
709 .magic = MODULE_MAGIC_INIT,
710 .name = "files",
711 .inst_size = sizeof(rlm_files_t),
713 },
714 .method_group = {
715 .bindings = (module_method_binding_t[]){
716 { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_files, .method_env = &method_env },
718 }
719 }
720};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define RCSID(id)
Definition build.h:485
#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 unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
#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
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
Definition cf_parse.c:1633
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:660
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:614
#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:283
#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:271
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:432
@ CONF_FLAG_FILE_READABLE
File matching value must exist, and must be readable.
Definition cf_parse.h:438
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:597
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:1625
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1581
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:286
#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:287
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:300
Specifies an attribute which must be present for the module to function.
Definition dict.h:286
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:299
#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
size_t fr_htrie_type_table_len
Definition htrie.c:36
fr_table_num_sorted_t const fr_htrie_type_table[]
Definition htrie.c:30
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:91
fr_htrie_type_t
Definition htrie.h:49
@ FR_HTRIE_TRIE
Data is stored in a prefix trie.
Definition htrie.h:53
@ FR_HTRIE_AUTO
Automatically choose the best type.
Definition htrie.h:54
@ 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 PERROR(_fmt,...)
Definition log.h:228
#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:1592
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:1872
talloc_free(reap)
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:792
int radius_legacy_map_list_apply(request_t *request, map_list_t const *list, fr_edit_list_t *el)
Definition pairmove.c:773
static const conf_parser_t config[]
Definition base.c:186
#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_UNLANG_FAIL
Definition rcode.h:59
#define RETURN_UNLANG_OK
Definition rcode.h:60
#define RETURN_UNLANG_NOOP
Definition rcode.h:65
fr_dict_attr_autoload_t rlm_files_dict_attr[]
Definition rlm_files.c:74
static int files_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:659
static int pairlist_to_key(uint8_t **out, size_t *outlen, void const *a)
Definition rlm_files.c:103
char const * filename
Definition rlm_files.c:40
PAIR_LIST_LIST * def
parsed files DEFAULT data.
Definition rlm_files.c:50
static int8_t pairlist_cmp(void const *a, void const *b)
Definition rlm_files.c:95
static const call_env_method_t method_env
Definition rlm_files.c:694
static fr_dict_attr_t const * attr_fall_through
Definition rlm_files.c:70
static unlang_action_t mod_files(UNUSED unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Initiate a files data lookup.
Definition rlm_files.c:645
static fr_dict_t const * dict_freeradius
Definition rlm_files.c:62
fr_htrie_t * htrie
parsed files "user" data.
Definition rlm_files.c:49
static int getrecv_filename(TALLOC_CTX *ctx, rlm_files_t const *inst, 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)
Definition rlm_files.c:108
tmpl_t * match_attr
Attribute to populate with matched key value.
Definition rlm_files.c:57
fr_htrie_type_t htype
Definition rlm_files.c:42
static uint32_t pairlist_hash(void const *a)
Definition rlm_files.c:90
fr_dict_autoload_t rlm_files_dict[]
Definition rlm_files.c:65
tmpl_t * key_tmpl
tmpl used to evaluate lookup key.
Definition rlm_files.c:48
rlm_files_data_t * data
Data from parsed call_env.
Definition rlm_files.c:56
static fr_dict_attr_t const * attr_next_shortest_prefix
Definition rlm_files.c:71
char const * name
Name of module instance - for debug output.
Definition rlm_files.c:58
fr_value_box_list_t values
Where the expanded tmpl value will be written.
Definition rlm_files.c:59
static const conf_parser_t module_config[]
Definition rlm_files.c:81
module_rlm_t rlm_files
Definition rlm_files.c:707
bool v3_compat
Definition rlm_files.c:41
static unlang_action_t mod_files_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Lookup the expanded key value in files data.
Definition rlm_files.c:411
Structure produced by custom call_env parser.
Definition rlm_files.c:47
Call_env structure.
Definition rlm_files.c:55
#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
struct map_s map_t
Definition map.h:33
char const * name
Instance name e.g. user_database.
Definition module.h:355
size_t inst_size
Size of the module's instance data.
Definition module.h:212
void * data
Module's instance data.
Definition module.h:291
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:152
Named methods exported by a module.
Definition module.h:174
#define tmpl_value(_tmpl)
Definition tmpl.h:937
#define tmpl_contains_regex(vpt)
Definition tmpl.h:226
#define tmpl_is_attr(vpt)
Definition tmpl.h:208
#define tmpl_is_exec(vpt)
Definition tmpl.h:211
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:142
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:138
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:206
#define tmpl_value_type(_tmpl)
Definition tmpl.h:939
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:335
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:801
#define tmpl_is_regex(vpt)
Definition tmpl.h:213
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:203
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:332
unlang_action_t unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *vpt, unlang_tmpl_args_t *args, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Push a pre-compiled tmpl and resumption state onto the stack for evaluation.
Definition module.c:216
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:273
#define talloc_get_type_abort_const
Definition talloc.h:287
char const * fr_tokens[T_TOKEN_LAST]
Definition token.c:79
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:199
@ 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:949
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:234
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:845
void fr_edit_list_abort(fr_edit_list_t *el)
Abort the entries in an edit list.
Definition edit.c:193
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:794
Track a series of edits.
Definition edit.c:101
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:455
uint32_t fr_value_box_hash(fr_value_box_t const *vb)
Hash the contents of a value box.
Definition value.c:6644
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
Definition value.c:612
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:743
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:4148
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)
Definition value.c:5754
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:4085
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:2283
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:4673
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:643
static fr_slen_t data
Definition value.h:1293
int nonnull(2, 5))
static size_t char ** out
Definition value.h:1023