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