The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
rlm_radius.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: 0db73c66d54bc2434bed40e210a58e990930cdc5 $
19 * @file rlm_radius.c
20 * @brief A RADIUS client library.
21 *
22 * @copyright 2016 The FreeRADIUS server project
23 * @copyright 2016 Network RADIUS SAS
24 */
25RCSID("$Id: 0db73c66d54bc2434bed40e210a58e990930cdc5 $")
26
27#include <freeradius-devel/io/application.h>
28#include <freeradius-devel/server/modpriv.h>
29#include <freeradius-devel/unlang/xlat_func.h>
30#include <freeradius-devel/util/debug.h>
31#include <freeradius-devel/util/dlist.h>
32
33#include "rlm_radius.h"
34
35static int mode_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
36static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
37static int status_check_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
38static int status_check_update_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
40
47
48/*
49 * "update" is not required.
50 *
51 * RFC 5997 Section 3 does not require the administrator provide anything:
52 * a Status-Server MUST carry Message-Authenticator, which the module adds
53 * to every packet, MAY carry NAS-Identifier and a NAS address, and SHOULD
54 * NOT carry anything else. status_check_alloc() supplies the
55 * NAS-Identifier when the map is empty, so a conformant packet does not
56 * need additional attributes.
57 */
62 { FR_CONF_OFFSET("num_answers_to_alive", rlm_radius_t, num_answers_to_alive), .dflt = STRINGIFY(3) },
63
65};
66
67/*
68 * Retransmission intervals for the packets we support.
69 */
71 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].irt), .dflt = STRINGIFY(2) },
72 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrt), .dflt = STRINGIFY(16) },
73 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrc), .dflt = STRINGIFY(5) },
74 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrd), .dflt = STRINGIFY(30) },
76};
77
79 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].irt), .dflt = STRINGIFY(2) },
80 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrt), .dflt = STRINGIFY(5) },
81 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrc), .dflt = STRINGIFY(1) },
82 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrd), .dflt = STRINGIFY(30) },
84};
85
87 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].irt), .dflt = STRINGIFY(2) },
88 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].mrt), .dflt = STRINGIFY(5) },
89 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].mrc), .dflt = STRINGIFY(5) },
90 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].mrd), .dflt = STRINGIFY(30) },
92};
93
95 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].irt), .dflt = STRINGIFY(2) },
96 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].mrt), .dflt = STRINGIFY(16) },
97 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].mrc), .dflt = STRINGIFY(5) },
98 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].mrd), .dflt = STRINGIFY(30) },
100};
101
103 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].irt), .dflt = STRINGIFY(2) },
104 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrt), .dflt = STRINGIFY(16) },
105 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrc), .dflt = STRINGIFY(5) },
106 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrd), .dflt = STRINGIFY(30) },
108};
109
110static conf_parser_t const udp_config[] = {
112
113#ifdef WITH_TLS
114 { FR_CONF_SUBSECTION_ALLOC("tls", CONF_FLAG_OK_MISSING, rlm_radius_t, tls_conf, fr_tls_client_config),
115 .subcs_type = "fr_tls_conf_t" },
116#endif
117
119};
120
121static conf_parser_t const tcp_config[] = {
123
124#ifdef WITH_TLS
125 { FR_CONF_SUBSECTION_ALLOC("tls", CONF_FLAG_OK_MISSING, rlm_radius_t, tls_conf, fr_tls_client_config),
126 .subcs_type = "fr_tls_conf_t" },
127#endif
128
130};
131
132/*
133 * We only parse the pool options if we're connected.
134 */
136 { FR_CONF_POINTER("status_check", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) status_check_config },
137
138 { FR_CONF_OFFSET_SUBSECTION("pool", 0, rlm_radius_t, trunk_conf, trunk_config ) },
139
140 { FR_CONF_POINTER("udp", 0, CONF_FLAG_SUBSECTION | CONF_FLAG_OPTIONAL, NULL), .subcs = (void const *) udp_config },
141
142 { FR_CONF_POINTER("tcp", 0, CONF_FLAG_SUBSECTION | CONF_FLAG_OPTIONAL, NULL), .subcs = (void const *) tcp_config },
143
145};
146
147/*
148 * We only parse the pool options if we're connected.
149 */
150static conf_parser_t const pool_config[] = {
151 { FR_CONF_POINTER("status_check", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) status_check_config },
152
153 { FR_CONF_OFFSET_SUBSECTION("pool", 0, rlm_radius_t, trunk_conf, trunk_config ) },
154
156};
157
158/*
159 * A mapping of configuration file names to internal variables.
160 */
161static conf_parser_t const module_config[] = {
162 { FR_CONF_OFFSET_FLAGS("mode", CONF_FLAG_REQUIRED, rlm_radius_t, mode), .func = mode_parse, .dflt = "proxy" },
163
165
167 .func = type_parse },
168
169 { FR_CONF_OFFSET("max_packet_size", rlm_radius_t, max_packet_size), .dflt = "4096" },
170 { FR_CONF_OFFSET("max_send_coalesce", rlm_radius_t, max_send_coalesce), .dflt = "1024" },
171
172 { FR_CONF_OFFSET("max_attributes", rlm_radius_t, max_attributes), .dflt = STRINGIFY(RADIUS_MAX_ATTRIBUTES) },
173
174 { FR_CONF_OFFSET("require_message_authenticator", rlm_radius_t, require_message_authenticator),
175 .func = cf_table_parse_uint8,
177 .dflt = "no" },
178
179 { FR_CONF_OFFSET("track_load_balance", rlm_radius_t, track_load_balance), },
180
181 { FR_CONF_OFFSET("response_window", rlm_radius_t, response_window), .dflt = STRINGIFY(20) },
182
183 { FR_CONF_OFFSET("zombie_period", rlm_radius_t, zombie_period), .dflt = STRINGIFY(40) },
184
185 { FR_CONF_OFFSET("revive_interval", rlm_radius_t, revive_interval) },
186
187 { FR_CONF_OFFSET("home_server_lifetime", rlm_radius_t, home_server_lifetime) },
188
190};
191
193 [FR_RADIUS_CODE_ACCESS_REQUEST] = { FR_CONF_POINTER("Access-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) auth_config },
194
195 [FR_RADIUS_CODE_ACCOUNTING_REQUEST] = { FR_CONF_POINTER("Accounting-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) acct_config },
196 [FR_RADIUS_CODE_STATUS_SERVER] = { FR_CONF_POINTER("Status-Server", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) status_config },
197 [FR_RADIUS_CODE_COA_REQUEST] = { FR_CONF_POINTER("CoA-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) coa_config },
198 [FR_RADIUS_CODE_DISCONNECT_REQUEST] = { FR_CONF_POINTER("Disconnect-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) disconnect_config },
199};
200
201static fr_dict_t const *dict_radius;
202
205 { .out = &dict_radius, .proto = "radius" },
207};
208
214
228
231 { .out = &attr_chap_challenge, .name = "CHAP-Challenge", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
232 { .out = &attr_chap_password, .name = "CHAP-Password", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
233 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
234 { .out = &attr_proxy_state, .name = "Proxy-State", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
235 { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
236
237 { .out = &attr_error_cause, .name = "Error-Cause", .type = FR_TYPE_UINT32, .dict = &dict_radius },
238 { .out = &attr_event_timestamp, .name = "Event-Timestamp", .type = FR_TYPE_DATE, .dict = &dict_radius},
239 { .out = &attr_extended_attribute_1, .name = "Extended-Attribute-1", .type = FR_TYPE_TLV, .dict = &dict_radius},
240 { .out = &attr_digest_attributes, .name = "Digest-Attributes", .type = FR_TYPE_TLV, .dict = &dict_radius},
241 { .out = &attr_digest_response, .name = "Digest-Response", .type = FR_TYPE_STRING, .dict = &dict_radius},
242 { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
243 { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
244 { .out = &attr_nas_identifier, .name = "NAS-Identifier", .type = FR_TYPE_STRING, .dict = &dict_radius},
245 { .out = &attr_original_packet_code, .name = "Extended-Attribute-1.Original-Packet-Code", .type = FR_TYPE_UINT32, .dict = &dict_radius},
246 { .out = &attr_reply_message, .name = "Reply-Message", .type = FR_TYPE_STRING, .dict = &dict_radius},
247 { .out = &attr_response_length, .name = "Extended-Attribute-1.Response-Length", .type = FR_TYPE_UINT32, .dict = &dict_radius },
248 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius},
249 { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius},
250
252};
253
254#include "bio.c"
255
257 { L("client"), RLM_RADIUS_MODE_CLIENT },
258 { L("dynamic-proxy"), RLM_RADIUS_MODE_XLAT_PROXY },
259 { L("proxy"), RLM_RADIUS_MODE_PROXY },
260 { L("replicate"), RLM_RADIUS_MODE_REPLICATE },
261 { L("unconnected-replicate"), RLM_RADIUS_MODE_UNCONNECTED_REPLICATE },
262};
264
265
266/** Set the mode of operation
267 *
268 * @param[in] ctx to allocate data in (instance of rlm_radius).
269 * @param[out] out Where to write the parsed data.
270 * @param[in] parent Base structure address.
271 * @param[in] ci #CONF_PAIR specifying the name of the type module.
272 * @param[in] rule unused.
273 * @return
274 * - 0 on success.
275 * - -1 on failure.
276 */
277static int mode_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
278 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
279{
280 char const *name = cf_pair_value(cf_item_to_pair(ci));
282 rlm_radius_t *inst = talloc_get_type_abort(parent, rlm_radius_t);
284
286
287 if (mode == RLM_RADIUS_MODE_INVALID) {
288 cf_log_err(ci, "Invalid mode name \"%s\"", name);
289 return -1;
290 }
291
292 *(rlm_radius_mode_t *) out = mode;
293
294 /*
295 * Normally we want connected sockets, in which case we push additional configuration for
296 * connected sockets.
297 */
298 switch (mode) {
299 default:
300 inst->fd_config.type = FR_BIO_FD_CONNECTED;
301
302 if (cf_section_rules_push(cs, connected_config) < 0) return -1;
303 break;
304
306 inst->fd_config.type = FR_BIO_FD_UNCONNECTED; /* reset later when the home server is allocated */
307
308 if (cf_section_rules_push(cs, pool_config) < 0) return -1;
309 break;
310
312 inst->fd_config.type = FR_BIO_FD_UNCONNECTED;
313 break;
314 }
315
316 return 0;
317}
318
319
320/** Set which types of packets we can parse
321 *
322 * @param[in] ctx to allocate data in (instance of rlm_radius).
323 * @param[out] out Where to write the parsed data.
324 * @param[in] parent Base structure address.
325 * @param[in] ci #CONF_PAIR specifying the name of the type module.
326 * @param[in] rule unused.
327 * @return
328 * - 0 on success.
329 * - -1 on failure.
330 */
331static int type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
332 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
333{
334 char const *type_str = cf_pair_value(cf_item_to_pair(ci));
336 fr_dict_enum_value_t const *type_enum;
337 uint32_t code;
338
339 /*
340 * Must be the RADIUS module
341 */
342 fr_assert(cs && (strcmp(cf_section_name1(cs), "radius") == 0));
343
344 /*
345 * Allow the process module to be specified by
346 * packet type.
347 */
348 type_enum = fr_dict_enum_by_name(attr_packet_type, type_str, -1);
349 if (!type_enum) {
350 invalid_code:
351 cf_log_err(ci, "Unknown or invalid RADIUS packet type '%s'", type_str);
352 return -1;
353 }
354
355 code = type_enum->value->vb_uint32;
356
357 /*
358 * Status-Server packets cannot be proxied.
359 */
360 if (code == FR_RADIUS_CODE_STATUS_SERVER) {
361 cf_log_err(ci, "Invalid setting of 'type = Status-Server'. Status-Server packets cannot be proxied.");
362 return -1;
363 }
364
365 if (!code ||
366 (code >= FR_RADIUS_CODE_MAX)) goto invalid_code;
367
368 if (!type_interval_config[code].name1) {
369 cf_log_err(ci, "Invalid packet type '%s' - cannot proxy a response packet", type_str);
370 return -1;
371 }
372
373 /*
374 * If we're doing async proxying, push the timers for the
375 * various packet types.
376 */
378
379 *(uint32_t *) out = code;
380
381 return 0;
382}
383
384/** Allow for Status-Server ping checks
385 *
386 * @param[in] ctx to allocate data in (instance of proto_radius).
387 * @param[out] out Where to write our parsed data.
388 * @param[in] parent Base structure address.
389 * @param[in] ci #CONF_PAIR specifying the name of the type module.
390 * @param[in] rule unused.
391 * @return
392 * - 0 on success.
393 * - -1 on failure.
394 */
395static int status_check_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
396 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
397{
398 char const *type_str = cf_pair_value(cf_item_to_pair(ci));
400 fr_dict_enum_value_t const *type_enum;
401 uint32_t code;
402
403 /*
404 * Allow the process module to be specified by
405 * packet type.
406 */
407 type_enum = fr_dict_enum_by_name(attr_packet_type, type_str, -1);
408 if (!type_enum) {
409 invalid_code:
410 cf_log_err(ci, "Unknown or invalid RADIUS packet type '%s'", type_str);
411 return -1;
412 }
413
414 code = type_enum->value->vb_uint32;
415
416 /*
417 * Cheat, and reuse the "type" array for allowed packet
418 * types.
419 */
420 if (!code ||
421 (code >= FR_RADIUS_CODE_MAX) ||
422 (!type_interval_config[code].name1)) goto invalid_code;
423
424 /*
425 * Add irt / mrt / mrd / mrc parsing, in the parent
426 * configuration section.
427 */
429
430 memcpy(out, &code, sizeof(code));
431
433
434 return 0;
435}
436
437static int status_check_verify(map_t *map, void *ctx)
438{
440 fr_dict_attr_t const *da;
441
443
444 if (unlang_fixup_update(map, NULL) < 0) return -1;
445
446 if (!map->rhs) return 0;
447
448 if (tmpl_is_xlat(map->rhs)) {
449 if (xlat_impure_func(tmpl_xlat(map->rhs))) {
450 invalid_xlat:
451 cf_log_err(map->ci, "Cannot assign dynamic values here");
452 return -1;
453 }
454 } else if (!tmpl_is_data(map->rhs)) {
455 goto invalid_xlat;
456 }
457
458 da = tmpl_attr_tail_da(map->lhs);
459
460 /*
461 * Ignore internal attributes.
462 */
463 if (da->flags.internal) {
464 cf_log_err(map->ci, "Cannot use internal attributes");
465 return -1;
466 }
467
468 /*
469 * Ignore signalling attributes. They shouldn't exist.
470 */
471 if ((da == attr_proxy_state) ||
473 cannot_use:
474 cf_log_err(map->ci, "Cannot use %s here.", da->name);
475 return -1;
476 }
477
478 /*
479 * Allow passwords only in Access-Request packets.
480 */
481 if ((inst->status_check != FR_RADIUS_CODE_ACCESS_REQUEST) &&
482 ((da == attr_user_password) || (da == attr_chap_password) || (da == attr_eap_message))) {
483 goto cannot_use;
484 }
485
486 /*
487 * RFC 5997 Section 5 says these MUST NOT be in Status-Server.
488 * The passwords are covered above.
489 */
490 if ((inst->status_check == FR_RADIUS_CODE_STATUS_SERVER) &&
491 ((da == attr_user_name) || (da == attr_reply_message) ||
492 (da == attr_digest_response) || (da == attr_digest_attributes) ||
493 (da->parent == attr_digest_attributes))) {
494 goto cannot_use;
495 }
496
497 return 0;
498}
499
500/** Allow the admin to set packet contents for Status-Server ping checks
501 *
502 * @param[in] ctx to allocate data in (instance of proto_radius).
503 * @param[out] out Where to write our parsed data
504 * @param[in] parent Base structure address.
505 * @param[in] ci #CONF_SECTION specifying the things to update
506 * @param[in] rule unused.
507 * @return
508 * - 0 on success.
509 * - -1 on failure.
510 */
511static int status_check_update_parse(TALLOC_CTX *ctx, void *out, void *parent,
512 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
513{
514 int rcode;
515 CONF_SECTION *cs;
516 char const *name2;
517 map_list_t *head = (map_list_t *)out;
518
520 map_list_init(head);
521
522 cs = cf_item_to_section(ci);
523 name2 = cf_section_name2(cs);
524 if (name2 && (strcmp(name2, "request") != 0)) {
525 cf_log_err(cs, "Only 'request' can be specified as the destination list");
526 return -1;
527 }
528
529 /*
530 * Compile the "update" section.
531 */
532 {
533 tmpl_rules_t parse_rules = {
534 .attr = {
536 .namespace = fr_dict_root(dict_radius),
537 .list_def = request_attr_request,
538 .list_presence = TMPL_ATTR_LIST_FORBID,
539 },
540 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
541 };
542
543 rcode = map_afrom_cs(ctx, head, cs, &parse_rules, &parse_rules, status_check_verify, parent, 128);
544 if (rcode < 0) return -1; /* message already printed */
545
546 /*
547 * status_check_alloc() supplies a NAS-Identifier when the
548 * map is empty, so an empty map needs no error here.
549 */
550 }
551
552 /*
553 * Rely on "bootstrap" to do sanity checks between 'type
554 * = Access-Request', and 'update' containing passwords.
555 */
556 return 0;
557}
558
559
560/** Do any RADIUS-layer fixups for proxying.
561 *
562 */
564{
565 fr_pair_t *vp;
566
567 /*
568 * If we received a Status-Server packet from the network, then don't proxy it.
569 *
570 * But we do sneakily allow virtual servers to originate and then send Status-Server packets.
571 */
572 if ((request->packet->code == FR_RADIUS_CODE_STATUS_SERVER) &&
573 ((request->packet->socket.af == AF_INET) || (request->packet->socket.af == AF_INET6))) {
574 RWDEBUG("Status-Server is reserved for internal use, and cannot be proxied.");
575 return 0;
576 }
577
578 if (!inst->allowed[request->packet->code]) {
579 REDEBUG("Packet code %s is disallowed by the configuration",
580 fr_radius_packet_name[request->packet->code]);
581 return -1;
582 }
583
584 /*
585 * Check for proxy loops.
586 *
587 * There should _never_ be two instances of the same Proxy-State in the packet.
588 */
589 if ((inst->mode == RLM_RADIUS_MODE_PROXY) && RDEBUG_ENABLED) {
590 unsigned int count = 0;
591 fr_dcursor_t cursor;
592
593 for (vp = fr_pair_dcursor_by_da_init(&cursor, &request->request_pairs, attr_proxy_state);
594 vp;
595 vp = fr_dcursor_next(&cursor)) {
596 if (vp->vp_length != sizeof(inst->common_ctx.proxy_state)) continue;
597
598 if (memcmp(vp->vp_octets, &inst->common_ctx.proxy_state,
599 sizeof(inst->common_ctx.proxy_state)) == 0) {
600
601 /*
602 * Cancel proxying when there are two instances of the same Proxy-State
603 * in the packet. This limitation could be configurable, but it likely
604 * doesn't make sense to make it configurable.
605 */
606 if (count == 1) {
607 RWARN("Canceling proxy due to loop of multiple %pV", vp);
608 return -1;
609 }
610
611 RWARN("Proxied packet contains our own %pV", vp);
612 RWARN("Check if there is a proxy loop. Perhaps the server has been configured to proxy to itself.");
613 count++;
614 }
615 }
616 }
617
618 if (request->packet->code != FR_RADIUS_CODE_ACCESS_REQUEST) return 0;
619
620 if (fr_pair_find_by_da(&request->request_pairs, NULL, attr_chap_password) &&
621 !fr_pair_find_by_da(&request->request_pairs, NULL, attr_chap_challenge)) {
623 fr_pair_value_memdup(vp, request->packet->vector, sizeof(request->packet->vector), true);
624 }
625
626 return 0;
627}
628
629
630/** Send packets outbound.
631 *
632 */
634{
636 bio_thread_t *thread = talloc_get_type_abort(mctx->thread, bio_thread_t);
637 fr_client_t *client;
638 int rcode;
639 bio_request_t *u = NULL;
640 fr_retry_config_t const *retry_config = NULL;
641
642 if (!request->packet->code) {
643 REDEBUG("You MUST specify a packet code");
645 }
646
647 if ((request->packet->code >= FR_RADIUS_CODE_MAX) ||
648 !fr_time_delta_ispos(inst->retry[request->packet->code].irt)) { /* can't be zero */
649 REDEBUG("Invalid packet code %u", request->packet->code);
651 }
652
653 /*
654 * Unconnected sockets use %radius.sendto.ipaddr(ip, port, secret)
655 */
657 (inst->mode == RLM_RADIUS_MODE_XLAT_PROXY)) {
658 REDEBUG("When using 'mode = %s', this module cannot be used in-place. "
659 "Instead, it must be called via a function call",
660 fr_table_str_by_value(mode_names, inst->mode, "<INVALID>"));
662 }
663
665 if (client && client->dynamic && !client->active) {
666 REDEBUG("Cannot proxy packets which define dynamic clients");
668 }
669
670 /*
671 * Push the request and it's data to the IO submodule.
672 *
673 * This may return YIELD, for "please yield", or it may
674 * return another code which indicates what happened to
675 * the request...
676 */
677 rcode = mod_enqueue(&u, &retry_config, inst, thread->ctx.trunk, request);
678 if (rcode == 0) RETURN_UNLANG_NOOP;
679 if (rcode < 0) RETURN_UNLANG_FAIL;
680
682}
683
684
685static int mod_instantiate(module_inst_ctx_t const *mctx)
686{
687 size_t i, num_types;
688 rlm_radius_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_radius_t);
689 CONF_SECTION *conf = mctx->mi->conf;
690
691 inst->name = mctx->mi->name;
692 inst->received_message_authenticator = talloc_zero(NULL, bool); /* Allocated outside of inst to default protection */
693
694#ifdef WITH_TLS
695 /*
696 * TLS and DTLS need a connected socket, and a trunk to manage the connections.
697 */
698 if (inst->tls_conf) {
699 char const *fixed_secret;
700 CONF_SECTION *wrong_cs;
701
702 if ((inst->mode != RLM_RADIUS_MODE_PROXY) && (inst->mode != RLM_RADIUS_MODE_CLIENT)) {
703 cf_log_err(conf, "The 'tls' section can only be used with 'mode = proxy' or 'mode = client'");
704 return -1;
705 }
706
707 /*
708 * The 'tls' section is only parsed inside of the 'tcp' or 'udp' section. Make sure that
709 * the section matches the transport, as src/lib/tls/ uses the transport to select
710 * between TLS and DTLS.
711 */
712 wrong_cs = cf_section_find(conf, (inst->fd_config.socket_type == SOCK_DGRAM) ? "tcp" : "udp", NULL);
713 if (wrong_cs && cf_section_find(wrong_cs, "tls", NULL)) {
714 cf_log_err(conf, "The 'tls' section is in the '%s' section, which does not match 'transport = %s'",
715 cf_section_name1(wrong_cs),
716 (inst->fd_config.socket_type == SOCK_DGRAM) ? "udp" : "tcp");
717 return -1;
718 }
719
720 inst->tls_conf->socket_type = inst->fd_config.socket_type;
721
722 /*
723 * RFC 6614 Section 2.1 says that the port is 2083, and Section 2.3 (4) says that the secret
724 * is "radsec". RFC 7360 Section 3.1 says that the DTLS port is UDP/2083, and Section 2.1
725 * says that the secret is "radius/dtls".
726 */
727 if (!inst->fd_config.dst_port) inst->fd_config.dst_port = 2083;
728
729 fixed_secret = (inst->fd_config.socket_type == SOCK_DGRAM) ? "radius/dtls" : "radsec";
730
731 if (!inst->secret) {
732 MEM(inst->secret = talloc_strdup(inst, fixed_secret));
733
734 } else if (strcmp(inst->secret, fixed_secret) != 0) {
735 cf_log_warn(conf, "The RFC says that the secret should be '%s'. A different secret may not work.",
736 fixed_secret);
737 }
738 } else
739#endif
740 /*
741 * Only the connected modes parse the 'tcp' and 'udp' sections, see mode_parse().
742 */
743 if (!inst->secret && (inst->fd_config.type == FR_BIO_FD_CONNECTED)) {
744 if (cf_section_find(conf, "tcp", NULL)) {
745 cf_log_err(conf, "Missing 'secret' in the 'tcp' section");
746 return -1;
747 }
748
749 if (cf_section_find(conf, "udp", NULL)) {
750 cf_log_err(conf, "Missing 'secret' in the 'udp' section");
751 return -1;
752 }
753 }
754
755 /*
756 * Replication is write-only, and append by default.
757 */
758 if (inst->mode == RLM_RADIUS_MODE_REPLICATE) {
759 if (inst->fd_config.filename && (inst->fd_config.flags != O_WRONLY)) {
760 cf_log_info(conf, "Setting 'flags = write-only' for writing to a file");
761 }
762 inst->fd_config.flags = O_WRONLY | O_APPEND;
763
764 } else if (inst->fd_config.filename) {
765 cf_log_err(conf, "When using an output 'filename', you MUST set 'mode = replicate'");
766 return -1;
767
768 } else {
769 /*
770 * All other IO is read+write.
771 */
772 inst->fd_config.flags = O_RDWR;
773 }
774
775 if (fr_bio_fd_check_config(&inst->fd_config) < 0) {
776 cf_log_perr(conf, "Invalid configuration");
777 return -1;
778 }
779
780 /*
781 * Clamp max_packet_size first before checking recv_buff and send_buff
782 */
783 FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, >=, 64);
784 FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, <=, 65535);
785
786 /*
787 * Check invalid configurations.
788 */
789 switch (inst->mode) {
790 default:
791 /*
792 * Filenames are write-only, and cannot get response packets.
793 */
794 if (inst->fd_config.filename) {
795 cf_log_err(conf, "Cannot set 'filename' here - it is only supported for 'mode=replicate'");
796 return -1;
797 }
798
799 /*
800 * When we expect replies, we need to be able to open multiple source ports. So the
801 * admin can't force a particular source port.
802 */
803 if (inst->fd_config.src_port) {
804 cf_log_err(conf, "Cannot 'src_port' here - it can only be set for replicating packets");
805 return -1;
806 }
807
808 /*
809 * Encorce limits per trunk, due to the 8-bit ID space.
810 */
811 FR_INTEGER_BOUND_CHECK("trunk.per_connection_max", inst->trunk_conf.max_req_per_conn, >=, 2);
812 FR_INTEGER_BOUND_CHECK("trunk.per_connection_max", inst->trunk_conf.max_req_per_conn, <=, 255);
813 FR_INTEGER_BOUND_CHECK("trunk.per_connection_target", inst->trunk_conf.target_req_per_conn, <=, inst->trunk_conf.max_req_per_conn / 2);
814
815 /*
816 * This only applies for XLAT_PROXY, but what the heck.
817 */
818 FR_TIME_DELTA_BOUND_CHECK("home_server_lifetime", inst->home_server_lifetime, >=, fr_time_delta_from_sec(10));
819 FR_TIME_DELTA_BOUND_CHECK("home_server_lifetime", inst->home_server_lifetime, <=, fr_time_delta_from_sec(3600));
820
821 /*
822 * No src_port range, we don't need to check any other settings.
823 */
824 if (!inst->fd_config.src_port_start && !inst->fd_config.src_port_end) break;
825
826 if (inst->fd_config.path) {
827 cf_log_err(conf, "Cannot set 'src_port_start' or 'src_port_end' for outgoing Unix sockets");
828 return -1;
829 }
830
831 /*
832 * Cross-check src_port, src_port_start, and src_port_end.
833 */
834 if (inst->fd_config.src_port_start) {
835 if (!inst->fd_config.src_port_end) {
836 cf_log_err(conf, "Range has 'src_port_start', but is missing 'src_port_end'");
837 return -1;
838 }
839
840 if (inst->fd_config.src_port_start >= inst->fd_config.src_port_end) {
841 cf_log_err(conf, "Range has invalid values for 'src_port_start' ... 'src_port_end'");
842 return -1;
843 }
844
845 } else if (inst->fd_config.src_port_end) {
846 cf_log_err(conf, "Range has 'src_port_end', but is missing 'src_port_start'");
847 return -1;
848 }
849
850 /*
851 * The source port range is split by worker - so there needs to be sufficient for at least
852 * one per worker.
853 */
854 if ((inst->fd_config.src_port_end - inst->fd_config.src_port_start + 1) < (int) main_config->max_workers) {
855 cf_log_perr(conf, "src_port_start / end range is not enough for %u worker threads",
857 return -1;
858 }
859
860 /*
861 * If there is a limited source port range, then set the reuse port flag. This lets us
862 * bind multiple sockets to the same port before we connect() them.
863 */
864 inst->fd_config.reuse_port = 1;
865 break;
866
868 /*
869 * Replication to dynamic filenames or dynamic unix sockets isn't supported.
870 */
871 if (inst->fd_config.filename || inst->fd_config.path) {
872 cf_log_err(conf, "Cannot set 'filename' or 'path' when using 'mode=unconnected-replicate'");
873 return -1;
874 }
875
876 /*
877 * Unconnected replicate has to use UDP.
878 */
879 if (inst->fd_config.socket_type != SOCK_DGRAM) {
880 cf_log_err(conf, "Cannot use TCP sockets with 'mode=unconnected-replicate'");
881 return -1;
882 }
883
885
887 /*
888 * We can force the source port, but then we have to set SO_REUSEPORT.
889 */
890 inst->fd_config.reuse_port = (inst->fd_config.src_port != 0);
891
892 /*
893 * Files and unix sockets are OK. The src_port can be set (or not), and that's fine.
894 */
895 if (inst->fd_config.src_port_start || inst->fd_config.src_port_end) {
896 cf_log_err(conf, "Cannot set 'src_port_start' or 'src_port_end' when replicating packets");
897 return -1;
898 }
899 break;
900 }
901
902 /*
903 * We allow what may otherwise be conflicting configurations, because the BIO code will pick one
904 * path, and the conflicts won't affect anything else. Only the src_port range is special.
905 */
906
907 FR_TIME_DELTA_BOUND_CHECK("response_window", inst->response_window, >=, fr_time_delta_from_sec(1));
908 FR_TIME_DELTA_BOUND_CHECK("response_window", inst->response_window, <=, fr_time_delta_from_sec(120));
909
910 FR_TIME_DELTA_BOUND_CHECK("zombie_period", inst->zombie_period, >=, fr_time_delta_from_sec(1));
911 FR_TIME_DELTA_BOUND_CHECK("zombie_period", inst->zombie_period, <=, fr_time_delta_from_sec(120));
912
913 if (!inst->status_check) {
914 FR_TIME_DELTA_BOUND_CHECK("revive_interval", inst->revive_interval, >=, fr_time_delta_from_sec(10));
915 FR_TIME_DELTA_BOUND_CHECK("revive_interval", inst->revive_interval, <=, fr_time_delta_from_sec(3600));
916 }
917
918 num_types = talloc_array_length(inst->types);
919 fr_assert(num_types > 0);
920
921 inst->timeout_retry = (fr_retry_config_t) {
922 .mrc = 1,
923 .mrd = inst->response_window,
924 };
925
926 inst->common_ctx = (fr_radius_ctx_t) {
927 .secret = inst->secret,
928 .secret_length = inst->secret ? talloc_strlen(inst->secret) : 0,
929 .proxy_state = ((uint64_t) fr_rand()) << 32 | fr_rand(),
930 };
931
932 /*
933 * Allow for O(1) lookup later...
934 */
935 for (i = 0; i < num_types; i++) {
936 uint32_t code;
937
938 code = inst->types[i];
939 fr_assert(code > 0);
941
942 if (inst->allowed[code]) {
943 cf_log_err(conf, "Duplicate 'type = %s'", fr_radius_packet_name[code]);
944 return -1;
945 }
946
947 inst->allowed[code] = true;
948 }
949
950 fr_assert(inst->status_check < FR_RADIUS_CODE_MAX);
951
952 /*
953 * If we're replicating, we don't care if the other end
954 * is alive.
955 */
956 if (inst->status_check) {
957 if (inst->mode == RLM_RADIUS_MODE_REPLICATE) {
958 cf_log_warn(conf, "Ignoring 'status_check = %s' due to 'mode = replicate'",
959 fr_radius_packet_name[inst->status_check]);
960 inst->status_check = false;
961
962 } else if ((inst->mode == RLM_RADIUS_MODE_UNCONNECTED_REPLICATE) ||
963 (inst->mode == RLM_RADIUS_MODE_XLAT_PROXY)) {
964 cf_log_warn(conf, "Ignoring 'status_check = %s' due to 'mode' setting",
965 fr_radius_packet_name[inst->status_check]);
966 inst->status_check = false;
967 }
968 }
969
970 /*
971 * If we have status checks, then do some sanity checks.
972 * Status-Server is always allowed. Otherwise, the
973 * status checks have to match one of the allowed
974 * packets.
975 */
976 if (inst->status_check) {
977 if (inst->status_check == FR_RADIUS_CODE_STATUS_SERVER) {
978 inst->allowed[inst->status_check] = true;
979
980 } else if (!inst->allowed[inst->status_check]) {
981 cf_log_err(conf, "Using 'status_check = %s' requires also 'type = %s'",
982 fr_radius_packet_name[inst->status_check], fr_radius_packet_name[inst->status_check]);
983 return -1;
984 }
985
986 /*
987 * @todo - check the contents of the "update"
988 * section, to be sure that (e.g.) Access-Request
989 * contains User-Name, etc.
990 */
991
992 if (inst->fd_config.filename) {
993 cf_log_info(conf, "Disabling status checks for output file %s", inst->fd_config.filename);
994 inst->status_check = 0;
995 }
996 }
997
998 /*
999 * Files and unix sockets can just have us call write().
1000 */
1001 if (inst->fd_config.filename || inst->fd_config.path) {
1002 inst->max_send_coalesce = 1;
1003 }
1004
1005 inst->trunk_conf.req_pool_headers = 4; /* One for the request, one for the buffer, one for the tracking binding, one for Proxy-State VP */
1006 inst->trunk_conf.req_pool_size = 1024 + sizeof(fr_pair_t) + 20;
1007
1008 if (inst->trunk_conf.conn_triggers) {
1010 char *server = NULL;
1011
1013 .module = mctx->mi->module->name,
1014 .name = inst->name
1015 };
1016
1017 /*
1018 * Only client and proxy mode have fixed destinations
1019 */
1020 if ((inst->mode == RLM_RADIUS_MODE_CLIENT) || (inst->mode == RLM_RADIUS_MODE_PROXY)) {
1021 fr_value_box_aprint(inst, &server, fr_box_ipaddr(inst->fd_config.dst_ipaddr), NULL);
1022 args.server = server;
1023 args.port = inst->fd_config.dst_port;
1024 }
1025
1026 MEM(inst->trigger_args = fr_pair_list_alloc(inst));
1027 if (module_trigger_args_build(inst->trigger_args, inst->trigger_args,
1028 cf_section_find(conf, "pool", NULL), &args) < 0) return -1;
1029 }
1030
1031 /*
1032 * Only check the async timers when we're acting as a client.
1033 */
1034 if (inst->mode != RLM_RADIUS_MODE_CLIENT) {
1035 return 0;
1036 }
1037
1038 /*
1039 * Set limits on retransmission timers
1040 */
1041 if (inst->allowed[FR_RADIUS_CODE_ACCESS_REQUEST]) {
1042 FR_TIME_DELTA_BOUND_CHECK("Access-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].irt, >=, fr_time_delta_from_sec(1));
1043 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
1044 FR_INTEGER_BOUND_CHECK("Access-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrc, >=, 1);
1045 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrd, >=, fr_time_delta_from_sec(5));
1046
1047 FR_TIME_DELTA_BOUND_CHECK("Access-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].irt, <=, fr_time_delta_from_sec(15));
1048 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrt, <=, fr_time_delta_from_sec(30));
1049 FR_INTEGER_BOUND_CHECK("Access-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrc, <=, 10);
1050 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrd, <=, fr_time_delta_from_sec(90));
1051 }
1052
1053 /*
1054 * Note that RFC 5080 allows for Accounting-Request to
1055 * have mrt=mrc=mrd = 0, which means "retransmit
1056 * forever". We allow that, with the restriction that
1057 * the server core will automatically free the request at
1058 * request.timeout.
1059 */
1061 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].irt, >=, fr_time_delta_from_sec(1));
1062#if 0
1063 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
1064 FR_INTEGER_BOUND_CHECK("Accounting-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrc, >=, 0);
1065 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrd, >=, fr_time_delta_from_sec(0));
1066#endif
1067
1068 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].irt, <=, fr_time_delta_from_sec(5));
1069 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrt, <=, fr_time_delta_from_sec(30));
1070 FR_INTEGER_BOUND_CHECK("Accounting-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrc, <=, 10);
1071 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrd, <=, fr_time_delta_from_sec(30));
1072 }
1073
1074 /*
1075 * Status-Server
1076 */
1077 if (inst->allowed[FR_RADIUS_CODE_STATUS_SERVER]) {
1078 FR_TIME_DELTA_BOUND_CHECK("Status-Server.initial_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].irt, >=, fr_time_delta_from_sec(1));
1079 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrt, >=, fr_time_delta_from_sec(5));
1080 FR_INTEGER_BOUND_CHECK("Status-Server.max_rtx_count", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrc, >=, 1);
1081 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_duration", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrd, >=, fr_time_delta_from_sec(5));
1082
1083 FR_TIME_DELTA_BOUND_CHECK("Status-Server.initial_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].irt, <=, fr_time_delta_from_sec(5));
1084 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrt, <=, fr_time_delta_from_sec(30));
1085 FR_INTEGER_BOUND_CHECK("Status-Server.max_rtx_count", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrc, <=, 10);
1086 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_duration", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrd, <=, fr_time_delta_from_sec(30));
1087 }
1088
1089 /*
1090 * CoA
1091 */
1092 if (inst->allowed[FR_RADIUS_CODE_COA_REQUEST]) {
1093 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].irt, >=, fr_time_delta_from_sec(1));
1094 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
1095 FR_INTEGER_BOUND_CHECK("CoA-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrc, >=, 1);
1096 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrd, >=, fr_time_delta_from_sec(5));
1097
1098 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].irt, <=, fr_time_delta_from_sec(5));
1099 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrt, <=, fr_time_delta_from_sec(60));
1100 FR_INTEGER_BOUND_CHECK("CoA-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrc, <=, 10);
1101 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrd, <=, fr_time_delta_from_sec(30));
1102 }
1103
1104 /*
1105 * Disconnect
1106 */
1108 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].irt, >=, fr_time_delta_from_sec(1));
1109 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
1110 FR_INTEGER_BOUND_CHECK("Disconnect-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrc, >=, 1);
1111 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrd, >=, fr_time_delta_from_sec(5));
1112
1113 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].irt, <=, fr_time_delta_from_sec(5));
1114 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrt, <=, fr_time_delta_from_sec(30));
1115 FR_INTEGER_BOUND_CHECK("Disconnect-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrc, <=, 10);
1116 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrd, <=, fr_time_delta_from_sec(30));
1117 }
1118
1119 return 0;
1120}
1121
1122static int mod_bootstrap(module_inst_ctx_t const *mctx)
1123{
1124 xlat_t *xlat;
1125 rlm_radius_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_radius_t);
1126
1127 switch (inst->mode) {
1129 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "sendto.ipaddr", xlat_radius_replicate, FR_TYPE_VOID);
1131 break;
1132
1134 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "sendto.ipaddr", xlat_radius_client, FR_TYPE_UINT32);
1136 break;
1137
1138 default:
1139 break;
1140 }
1141
1142 return 0;
1143}
1144
1145
1146static int mod_detach(module_detach_ctx_t const *mctx)
1147{
1148 rlm_radius_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_radius_t);
1149
1150 talloc_free(inst->received_message_authenticator);
1151 return 0;
1152}
1153
1154static int mod_load(void)
1155{
1156 if (fr_radius_global_init() < 0) {
1157 PERROR("Failed initialising protocol library");
1158 return -1;
1159 }
1160 return 0;
1161}
1162
1163static void mod_unload(void)
1164{
1166}
1167
1168/*
1169 * The module name should be the only globally exported symbol.
1170 * That is, everything else should be 'static'.
1171 *
1172 * If the module needs to temporarily modify it's instantiation
1173 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
1174 * The server will then take care of ensuring that the module
1175 * is single-threaded.
1176 */
1179 .common = {
1180 .magic = MODULE_MAGIC_INIT,
1181 .name = "radius",
1182 .inst_size = sizeof(rlm_radius_t),
1184 .dict = &dict_radius,
1185
1186 .onload = mod_load,
1187 .unload = mod_unload,
1188
1189 .bootstrap = mod_bootstrap,
1190 .instantiate = mod_instantiate,
1191 .detach = mod_detach,
1192
1193 .thread_inst_size = sizeof(bio_thread_t),
1194 .thread_inst_type = "bio_thread_t",
1195 .thread_instantiate = mod_thread_instantiate,
1196 .thread_detach = mod_thread_detach,
1197 },
1198 .method_group = {
1199 .bindings = (module_method_binding_t[]){
1200 { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_process },
1202 },
1203 }
1204};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
va_list args
Definition acutest.h:923
static uint8_t request[4]
#define RCSID(id)
Definition build.h:603
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:245
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:422
#define STRINGIFY(x)
Definition build.h:233
#define UNUSED
Definition build.h:415
#define NUM_ELEMENTS(_t)
Definition build.h:437
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:722
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:666
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:572
#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
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:651
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:466
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:483
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition cf_parse.h:470
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:484
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
Definition cf_parse.h:495
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:491
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:460
#define FR_CONF_SUBSECTION_ALLOC(_name, _flags, _struct, _field, _subcs)
conf_parser_t which allocates a struct and populates it from a subsection
Definition cf_parse.h:384
int cf_table_parse_uint8(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:754
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition cf_parse.h:350
#define cf_section_rule_push(_cs, _rule)
Definition cf_parse.h:752
#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
#define FR_CONF_OFFSET_REF(_struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition cf_parse.h:337
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition cf_parse.h:309
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:583
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _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:238
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:649
Common header for all CONF_* types.
Definition cf_priv.h:54
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1405
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
Definition cf_util.c:1391
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1247
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:671
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:605
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:651
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1758
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:340
#define cf_log_info(_cf, _fmt,...)
Definition cf_util.h:342
#define cf_parent(_cf)
Definition cf_util.h:115
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:347
#define cf_log_warn(_cf, _fmt,...)
Definition cf_util.h:341
#define CF_IDENT_ANY
Definition cf_util.h:80
fr_dict_t * dict
Definition common.c:31
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
#define MEM(x)
Definition debug.h:38
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition defs.h:33
@ FR_RADIUS_CODE_DISCONNECT_REQUEST
RFC3575/RFC5176 - Disconnect-Request.
Definition defs.h:46
@ FR_RADIUS_CODE_MAX
Maximum possible protocol code.
Definition defs.h:53
@ FR_RADIUS_CODE_STATUS_SERVER
RFC2865/RFC5997 - Status Server (request)
Definition defs.h:44
@ FR_RADIUS_CODE_COA_REQUEST
RFC3575/RFC5176 - CoA-Request.
Definition defs.h:49
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
Definition defs.h:36
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2717
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:316
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:329
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:281
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:335
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3778
Specifies an attribute which must be present for the module to function.
Definition dict.h:315
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:328
Value of an enumerated attribute.
Definition dict.h:277
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
const conf_parser_t fr_bio_fd_client_config[]
Definition fd_config.c:314
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
Definition fd.h:63
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition fd.h:60
int fr_bio_fd_check_config(fr_bio_fd_config_t const *cfg)
Checks the configuration without modifying anything.
Definition fd_open.c:996
talloc_free(hp)
bool active
for dynamic clients
Definition client.h:114
bool dynamic
Whether the client was dynamically defined.
Definition client.h:113
Describes a host allowed to send packets to the server.
Definition client.h:80
#define PERROR(_fmt,...)
Definition log.h:233
#define RWDEBUG(fmt,...)
Definition log.h:378
#define RWARN(fmt,...)
Definition log.h:314
int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION const *cs, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, map_validate_t validate, void *uctx, unsigned int max)
Convert a config section into an attribute map.
Definition map.c:1168
main_config_t const * main_config
Main server configuration.
Definition main_config.c:56
uint32_t max_workers
for the scheduler
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
int unlang_fixup_update(map_t *map, void *ctx)
Validate and fixup a map that's part of an update section.
Definition compile.c:346
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * thread
Thread specific instance data.
Definition module_ctx.h:43
module_instance_t * mi
Module instance to detach.
Definition module_ctx.h:57
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for detach calls.
Definition module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Definition module_rlm.c:234
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
static int mod_enqueue(bio_request_t **p_u, fr_retry_config_t const **p_retry_config, rlm_radius_t const *inst, trunk_t *trunk, request_t *request)
Definition bio.c:3074
static void mod_retry(module_ctx_t const *mctx, request_t *request, fr_retry_t const *retry)
Handle module retries.
Definition bio.c:2061
bio_handle_ctx_t ctx
common struct for home servers and BIO handles
Definition bio.c:62
static xlat_action_t xlat_radius_replicate(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Definition bio.c:3373
static xlat_action_t xlat_radius_client(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Definition bio.c:3531
trunk_t * trunk
trunk handler
Definition bio.c:50
static xlat_arg_parser_t const xlat_radius_send_args[]
Definition bio.c:3363
Connect request_t to local tracking structure.
Definition bio.c:150
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2897
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
fr_pair_list_t * fr_pair_list_alloc(TALLOC_CTX *ctx)
Allocate a new pair list on the heap.
Definition pair.c:120
static const conf_parser_t config[]
Definition base.c:162
size_t fr_radius_require_ma_table_len
Definition base.c:93
int fr_radius_global_init(void)
Definition base.c:1313
void fr_radius_global_free(void)
Definition base.c:1337
fr_table_num_sorted_t const fr_radius_require_ma_table[]
Definition base.c:86
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Definition base.c:115
Functions to support RADIUS bio handlers.
#define fr_assert(_expr)
Definition rad_assert.h:37
static fr_bio_fd_config_t fd_config
static char * secret
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED()
#define RADIUS_MAX_ATTRIBUTES
Definition radius.h:39
static rs_t * conf
Definition radsniff.c:52
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:128
#define RETURN_UNLANG_FAIL
Definition rcode.h:69
#define RETURN_UNLANG_NOOP
Definition rcode.h:75
fr_dict_attr_t const * request_attr_request
Definition request.c:43
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static unlang_action_t mod_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Resume a yielded module method after its delivery report has arrived.
Definition rlm_kafka.c:477
static conf_parser_t coa_config[]
Definition rlm_radius.c:94
static conf_parser_t disconnect_config[]
Definition rlm_radius.c:102
static int status_check_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int mod_detach(module_detach_ctx_t const *mctx)
static int mod_load(void)
static conf_parser_t const udp_config[]
Definition rlm_radius.c:110
static fr_dict_attr_t const * attr_packet_type
Definition rlm_radius.c:211
static fr_dict_attr_t const * attr_user_password
Definition rlm_radius.c:227
static fr_dict_attr_t const * attr_digest_response
Definition rlm_radius.c:219
static fr_dict_attr_t const * attr_state
Definition rlm_radius.c:213
static fr_dict_attr_t const * attr_eap_message
Definition rlm_radius.c:221
static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static conf_parser_t const pool_config[]
Definition rlm_radius.c:150
static fr_dict_attr_t const * attr_chap_password
Definition rlm_radius.c:210
static int status_check_verify(map_t *map, void *ctx)
Definition rlm_radius.c:437
static fr_dict_attr_t const * attr_digest_attributes
Definition rlm_radius.c:218
static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Send packets outbound.
Definition rlm_radius.c:633
static fr_dict_t const * dict_radius
Definition rlm_radius.c:201
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static fr_dict_attr_t const * attr_chap_challenge
Definition rlm_radius.c:209
static conf_parser_t status_config[]
Definition rlm_radius.c:86
fr_dict_attr_autoload_t rlm_radius_dict_attr[]
Definition rlm_radius.c:230
static fr_dict_attr_t const * attr_extended_attribute_1
Definition rlm_radius.c:217
static fr_dict_attr_t const * attr_reply_message
Definition rlm_radius.c:224
static fr_dict_attr_t const * attr_error_cause
Definition rlm_radius.c:215
static void mod_unload(void)
static fr_dict_attr_t const * attr_proxy_state
Definition rlm_radius.c:212
static int radius_fixups(rlm_radius_t const *inst, request_t *request)
Do any RADIUS-layer fixups for proxying.
Definition rlm_radius.c:563
static fr_dict_attr_t const * attr_nas_identifier
Definition rlm_radius.c:222
static conf_parser_t const type_interval_config[FR_RADIUS_CODE_MAX]
Definition rlm_radius.c:192
static conf_parser_t auth_config[]
Definition rlm_radius.c:70
static int mode_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static conf_parser_t const tcp_config[]
Definition rlm_radius.c:121
module_rlm_t rlm_radius
fr_dict_autoload_t rlm_radius_dict[]
Definition rlm_radius.c:204
static fr_dict_attr_t const * attr_user_name
Definition rlm_radius.c:226
static int status_check_update_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static fr_dict_attr_t const * attr_original_packet_code
Definition rlm_radius.c:223
static fr_dict_attr_t const * attr_event_timestamp
Definition rlm_radius.c:216
static conf_parser_t const status_check_update_config[]
Definition rlm_radius.c:58
static fr_dict_attr_t const * attr_response_length
Definition rlm_radius.c:225
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_radius.c:685
static conf_parser_t const status_check_config[]
Definition rlm_radius.c:41
static size_t mode_names_len
Definition rlm_radius.c:263
static fr_table_num_sorted_t mode_names[]
Definition rlm_radius.c:256
static conf_parser_t const module_config[]
Definition rlm_radius.c:161
static conf_parser_t const connected_config[]
Definition rlm_radius.c:135
static fr_dict_attr_t const * attr_message_authenticator
Definition rlm_radius.c:220
static conf_parser_t acct_config[]
Definition rlm_radius.c:78
struct rlm_radius_s rlm_radius_t
Definition rlm_radius.h:45
rlm_radius_mode_t
Definition rlm_radius.h:47
@ RLM_RADIUS_MODE_XLAT_PROXY
radius.sendto.ipaddr(), but we do look for a reply.
Definition rlm_radius.h:53
@ RLM_RADIUS_MODE_INVALID
Definition rlm_radius.h:48
@ RLM_RADIUS_MODE_PROXY
we proxy to one home server
Definition rlm_radius.h:49
@ RLM_RADIUS_MODE_REPLICATE
to a particular destination
Definition rlm_radius.h:51
@ RLM_RADIUS_MODE_UNCONNECTED_REPLICATE
radius.sendto.ipaddr(), but we don't look for a reply
Definition rlm_radius.h:52
@ RLM_RADIUS_MODE_CLIENT
we are a client to one home server
Definition rlm_radius.h:50
static char const * name
static conf_parser_t retry_config[]
Definition rlm_tacacs.c:38
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:39
char const * name
Instance name e.g. user_database.
Definition module.h:361
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:355
size_t inst_size
Size of the module's instance data.
Definition module.h:213
void * data
Module's instance data.
Definition module.h:297
void * boot
Data allocated during the boostrap phase.
Definition module.h:300
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:153
Named methods exported by a module.
Definition module.h:175
#define pair_append_request(_attr, _da)
Allocate and append a fr_pair_t to the request list.
Definition pair.h:37
#define tmpl_is_xlat(vpt)
Definition tmpl.h:217
#define tmpl_is_attr(vpt)
Definition tmpl.h:215
#define tmpl_xlat(_tmpl)
Definition tmpl.h:955
@ TMPL_ATTR_LIST_FORBID
Attribute refs are forbidden from having a list.
Definition tmpl.h:270
#define tmpl_is_data(vpt)
Definition tmpl.h:213
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:346
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:826
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:343
@ FR_SIGNAL_NONE
No signals.
Definition signal.h:39
fr_client_t * client_from_request(request_t *request)
Search up a list of requests trying to locate one which has a client.
Definition client.c:1158
return count
Definition module.c:155
unlang_action_t unlang_module_yield_to_retry(request_t *request, module_method_t resume, unlang_module_retry_t retry, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx, fr_retry_config_t const *retry_cfg)
Yield a request back to the interpreter, with retries.
Definition module.c:369
static void mod_signal(module_ctx_t const *mctx, request_t *request, UNUSED fr_signal_t action)
Cancel a call to a submodule.
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
eap_type_t type
The preferred EAP-Type of this instance of the EAP-SIM/AKA/AKA' state machine.
Value pair map.
Definition map.h:77
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
CONF_ITEM * ci
Config item that the map was created from.
Definition map.h:85
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:280
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:685
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
#define talloc_get_type_abort_const
Definition talloc.h:117
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:599
#define fr_time_delta_ispos(_a)
Definition time.h:290
int module_trigger_args_build(TALLOC_CTX *ctx, fr_pair_list_t *list, CONF_SECTION const *cs, module_trigger_args_t *args)
Build trigger args pair list for modules.
Definition trigger.c:504
Common values used by modules when building trigger args.
Definition trigger.h:42
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
Definition trunk.c:345
bool xlat_impure_func(xlat_exp_head_t const *head)
static fr_slen_t head
Definition xlat.h:410
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
Definition pair.h:640
struct value_pair_s fr_pair_t
Definition pair.h:48
static fr_slen_t parent
Definition pair.h:864
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
#define fr_box_ipaddr(_val)
Definition value.h:348
static fr_sbuff_err_t char ** out
Definition value.h:1061
int nonnull(2, 5))
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:178
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:374