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