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