The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_radius.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: dc2d89dbd0b4937fd8c4e415226ad33bf7546992 $
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: dc2d89dbd0b4937fd8c4e415226ad33bf7546992 $")
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);
39static int radius_fixups(rlm_radius_t const *inst, request_t *request);
40
47
52 { FR_CONF_OFFSET("num_answers_to_alive", rlm_radius_t, num_answers_to_alive), .dflt = STRINGIFY(3) },
53
55};
56
57/*
58 * Retransmission intervals for the packets we support.
59 */
61 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].irt), .dflt = STRINGIFY(2) },
62 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrt), .dflt = STRINGIFY(16) },
63 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrc), .dflt = STRINGIFY(5) },
64 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrd), .dflt = STRINGIFY(30) },
66};
67
69 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].irt), .dflt = STRINGIFY(2) },
70 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrt), .dflt = STRINGIFY(5) },
71 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrc), .dflt = STRINGIFY(1) },
72 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrd), .dflt = STRINGIFY(30) },
74};
75
77 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].irt), .dflt = STRINGIFY(2) },
78 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].mrt), .dflt = STRINGIFY(5) },
79 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].mrc), .dflt = STRINGIFY(5) },
80 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_STATUS_SERVER].mrd), .dflt = STRINGIFY(30) },
82};
83
85 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].irt), .dflt = STRINGIFY(2) },
86 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].mrt), .dflt = STRINGIFY(16) },
87 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].mrc), .dflt = STRINGIFY(5) },
88 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_COA_REQUEST].mrd), .dflt = STRINGIFY(30) },
90};
91
93 { FR_CONF_OFFSET("initial_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].irt), .dflt = STRINGIFY(2) },
94 { FR_CONF_OFFSET("max_rtx_time", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrt), .dflt = STRINGIFY(16) },
95 { FR_CONF_OFFSET("max_rtx_count", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrc), .dflt = STRINGIFY(5) },
96 { FR_CONF_OFFSET("max_rtx_duration", rlm_radius_t, retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrd), .dflt = STRINGIFY(30) },
98};
99
105
106/*
107 * We only parse the pool options if we're connected.
108 */
110 { FR_CONF_POINTER("status_check", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) status_check_config },
111
112 { FR_CONF_OFFSET_SUBSECTION("pool", 0, rlm_radius_t, trunk_conf, trunk_config ) },
113
114 { FR_CONF_POINTER("udp", 0, CONF_FLAG_SUBSECTION | CONF_FLAG_OPTIONAL, NULL), .subcs = (void const *) transport_config },
115
116 { FR_CONF_POINTER("tcp", 0, CONF_FLAG_SUBSECTION | CONF_FLAG_OPTIONAL, NULL), .subcs = (void const *) transport_config },
117
119};
120
121/*
122 * We only parse the pool options if we're connected.
123 */
124static conf_parser_t const pool_config[] = {
125 { FR_CONF_POINTER("status_check", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) status_check_config },
126
127 { FR_CONF_OFFSET_SUBSECTION("pool", 0, rlm_radius_t, trunk_conf, trunk_config ) },
128
130};
131
132/*
133 * A mapping of configuration file names to internal variables.
134 */
135static conf_parser_t const module_config[] = {
136 { FR_CONF_OFFSET_FLAGS("mode", CONF_FLAG_REQUIRED, rlm_radius_t, mode), .func = mode_parse, .dflt = "proxy" },
137
139
141 .func = type_parse },
142
143 { FR_CONF_OFFSET_FLAGS("replicate", CONF_FLAG_DEPRECATED, rlm_radius_t, replicate) },
144
145 { FR_CONF_OFFSET_FLAGS("synchronous", CONF_FLAG_DEPRECATED, rlm_radius_t, synchronous) },
146
147 { FR_CONF_OFFSET_FLAGS("originate", CONF_FLAG_DEPRECATED, rlm_radius_t, originate) },
148
149 { FR_CONF_OFFSET("max_packet_size", rlm_radius_t, max_packet_size), .dflt = "4096" },
150 { FR_CONF_OFFSET("max_send_coalesce", rlm_radius_t, max_send_coalesce), .dflt = "1024" },
151
152 { FR_CONF_OFFSET("max_attributes", rlm_radius_t, max_attributes), .dflt = STRINGIFY(RADIUS_MAX_ATTRIBUTES) },
153
154 { FR_CONF_OFFSET("require_message_authenticator", rlm_radius_t, require_message_authenticator),
155 .func = cf_table_parse_int,
157 .dflt = "no" },
158
159 { FR_CONF_OFFSET("response_window", rlm_radius_t, response_window), .dflt = STRINGIFY(20) },
160
161 { FR_CONF_OFFSET("zombie_period", rlm_radius_t, zombie_period), .dflt = STRINGIFY(40) },
162
163 { FR_CONF_OFFSET("revive_interval", rlm_radius_t, revive_interval) },
164
166};
167
169 [FR_RADIUS_CODE_ACCESS_REQUEST] = { FR_CONF_POINTER("Access-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) auth_config },
170
171 [FR_RADIUS_CODE_ACCOUNTING_REQUEST] = { FR_CONF_POINTER("Accounting-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) acct_config },
172 [FR_RADIUS_CODE_STATUS_SERVER] = { FR_CONF_POINTER("Status-Server", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) status_config },
173 [FR_RADIUS_CODE_COA_REQUEST] = { FR_CONF_POINTER("CoA-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) coa_config },
174 [FR_RADIUS_CODE_DISCONNECT_REQUEST] = { FR_CONF_POINTER("Disconnect-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) disconnect_config },
175};
176
177static fr_dict_t const *dict_radius;
178
181 { .out = &dict_radius, .proto = "radius" },
182 { NULL }
183};
184
189
199
202 { .out = &attr_chap_challenge, .name = "CHAP-Challenge", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
203 { .out = &attr_chap_password, .name = "CHAP-Password", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
204 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
205 { .out = &attr_proxy_state, .name = "Proxy-State", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
206
207 { .out = &attr_error_cause, .name = "Error-Cause", .type = FR_TYPE_UINT32, .dict = &dict_radius },
208 { .out = &attr_event_timestamp, .name = "Event-Timestamp", .type = FR_TYPE_DATE, .dict = &dict_radius},
209 { .out = &attr_extended_attribute_1, .name = "Extended-Attribute-1", .type = FR_TYPE_TLV, .dict = &dict_radius},
210 { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
211 { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
212 { .out = &attr_nas_identifier, .name = "NAS-Identifier", .type = FR_TYPE_STRING, .dict = &dict_radius},
213 { .out = &attr_original_packet_code, .name = "Extended-Attribute-1.Original-Packet-Code", .type = FR_TYPE_UINT32, .dict = &dict_radius},
214 { .out = &attr_response_length, .name = "Extended-Attribute-1.Response-Length", .type = FR_TYPE_UINT32, .dict = &dict_radius },
215 { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius},
216
217 { NULL }
218};
219
220#include "bio.c"
221
223 { L("client"), RLM_RADIUS_MODE_CLIENT },
224 { L("dynamic-proxy"), RLM_RADIUS_MODE_XLAT_PROXY },
225 { L("proxy"), RLM_RADIUS_MODE_PROXY },
226 { L("replicate"), RLM_RADIUS_MODE_REPLICATE },
227 { L("unconnected-replicate"), RLM_RADIUS_MODE_UNCONNECTED_REPLICATE },
228};
230
231
232/** Set the mode of operation
233 *
234 * @param[in] ctx to allocate data in (instance of rlm_radius).
235 * @param[out] out Where to write the parsed data.
236 * @param[in] parent Base structure address.
237 * @param[in] ci #CONF_PAIR specifying the name of the type module.
238 * @param[in] rule unused.
239 * @return
240 * - 0 on success.
241 * - -1 on failure.
242 */
243static int mode_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
244 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
245{
246 char const *name = cf_pair_value(cf_item_to_pair(ci));
248 rlm_radius_t *inst = talloc_get_type_abort(parent, rlm_radius_t);
250
252
253 /*
254 * Commented out until we upgrade the old configurations.
255 */
256 if (mode == RLM_RADIUS_MODE_INVALID) {
257 cf_log_err(ci, "Invalid mode name \"%s\"", name);
258 return -1;
259 }
260
261 *(rlm_radius_mode_t *) out = mode;
262
263 /*
264 * Normally we want connected sockets, in which case we push additional configuration for
265 * connected sockets.
266 */
267 switch (mode) {
268 default:
269 inst->fd_config.type = FR_BIO_FD_CONNECTED;
270
271 if (cf_section_rules_push(cs, connected_config) < 0) return -1;
272 break;
273
275 inst->fd_config.type = FR_BIO_FD_UNCONNECTED; /* reset later when the home server is allocated */
276
277 if (cf_section_rules_push(cs, pool_config) < 0) return -1;
278 break;
279
281 inst->fd_config.type = FR_BIO_FD_UNCONNECTED;
282 break;
283 }
284
285 return 0;
286}
287
288
289/** Set which types of packets we can parse
290 *
291 * @param[in] ctx to allocate data in (instance of rlm_radius).
292 * @param[out] out Where to write the parsed data.
293 * @param[in] parent Base structure address.
294 * @param[in] ci #CONF_PAIR specifying the name of the type module.
295 * @param[in] rule unused.
296 * @return
297 * - 0 on success.
298 * - -1 on failure.
299 */
300static int type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
301 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
302{
303 char const *type_str = cf_pair_value(cf_item_to_pair(ci));
305 fr_dict_enum_value_t const *type_enum;
306 uint32_t code;
307
308 /*
309 * Must be the RADIUS module
310 */
311 fr_assert(cs && (strcmp(cf_section_name1(cs), "radius") == 0));
312
313 /*
314 * Allow the process module to be specified by
315 * packet type.
316 */
317 type_enum = fr_dict_enum_by_name(attr_packet_type, type_str, -1);
318 if (!type_enum) {
319 invalid_code:
320 cf_log_err(ci, "Unknown or invalid RADIUS packet type '%s'", type_str);
321 return -1;
322 }
323
324 code = type_enum->value->vb_uint32;
325
326 /*
327 * Status-Server packets cannot be proxied.
328 */
329 if (code == FR_RADIUS_CODE_STATUS_SERVER) {
330 cf_log_err(ci, "Invalid setting of 'type = Status-Server'. Status-Server packets cannot be proxied.");
331 return -1;
332 }
333
334 if (!code ||
335 (code >= FR_RADIUS_CODE_MAX) ||
336 (!type_interval_config[code].name1)) goto invalid_code;
337
338 /*
339 * If we're doing async proxying, push the timers for the
340 * various packet types.
341 */
343
344 *(uint32_t *) out = code;
345
346 return 0;
347}
348
349/** Allow for Status-Server ping checks
350 *
351 * @param[in] ctx to allocate data in (instance of proto_radius).
352 * @param[out] out Where to write our parsed data.
353 * @param[in] parent Base structure address.
354 * @param[in] ci #CONF_PAIR specifying the name of the type module.
355 * @param[in] rule unused.
356 * @return
357 * - 0 on success.
358 * - -1 on failure.
359 */
360static int status_check_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
361 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
362{
363 char const *type_str = cf_pair_value(cf_item_to_pair(ci));
365 fr_dict_enum_value_t const *type_enum;
366 uint32_t code;
367
368 /*
369 * Allow the process module to be specified by
370 * packet type.
371 */
372 type_enum = fr_dict_enum_by_name(attr_packet_type, type_str, -1);
373 if (!type_enum) {
374 invalid_code:
375 cf_log_err(ci, "Unknown or invalid RADIUS packet type '%s'", type_str);
376 return -1;
377 }
378
379 code = type_enum->value->vb_uint32;
380
381 /*
382 * Cheat, and reuse the "type" array for allowed packet
383 * types.
384 */
385 if (!code ||
386 (code >= FR_RADIUS_CODE_MAX) ||
387 (!type_interval_config[code].name1)) goto invalid_code;
388
389 /*
390 * Add irt / mrt / mrd / mrc parsing, in the parent
391 * configuration section.
392 */
394
395 memcpy(out, &code, sizeof(code));
396
397 /*
398 * Nothing more to do here, so we stop.
399 */
400 if (code == FR_RADIUS_CODE_STATUS_SERVER) return 0;
401
403
404 return 0;
405}
406
407/** Allow the admin to set packet contents for Status-Server ping checks
408 *
409 * @param[in] ctx to allocate data in (instance of proto_radius).
410 * @param[out] out Where to write our parsed data
411 * @param[in] parent Base structure address.
412 * @param[in] ci #CONF_SECTION specifying the things to update
413 * @param[in] rule unused.
414 * @return
415 * - 0 on success.
416 * - -1 on failure.
417 */
418static int status_check_update_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
419 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
420{
421 int rcode;
422 CONF_SECTION *cs;
423 char const *name2;
424 map_list_t *head = (map_list_t *)out;
425
427 map_list_init(head);
428
429 cs = cf_item_to_section(ci);
430 name2 = cf_section_name2(cs);
431 if (!name2 || (strcmp(name2, "request") != 0)) {
432 cf_log_err(cs, "You must specify 'request' as the destination list");
433 return -1;
434 }
435
436 /*
437 * Compile the "update" section.
438 */
439 {
440 tmpl_rules_t parse_rules = {
441 .attr = {
443 }
444 };
445
446 rcode = map_afrom_cs(ctx, head, cs, &parse_rules, &parse_rules, unlang_fixup_update, NULL, 128);
447 if (rcode < 0) return -1; /* message already printed */
448 if (map_list_empty(head)) {
449 cf_log_err(cs, "'update' sections cannot be empty");
450 return -1;
451 }
452 }
453
454 /*
455 * Rely on "bootstrap" to do sanity checks between 'type
456 * = Access-Request', and 'update' containing passwords.
457 */
458 return 0;
459}
460
461
462/** Do any RADIUS-layer fixups for proxying.
463 *
464 */
465static int radius_fixups(rlm_radius_t const *inst, request_t *request)
466{
467 fr_pair_t *vp;
468
469 if (request->packet->code == FR_RADIUS_CODE_STATUS_SERVER) {
470 RWDEBUG("Status-Server is reserved for internal use, and cannot be sent manually.");
471 return 0;
472 }
473
474 if (!inst->allowed[request->packet->code]) {
475 REDEBUG("Packet code %s is disallowed by the configuration",
476 fr_radius_packet_name[request->packet->code]);
477 return -1;
478 }
479
480 /*
481 * Check for proxy loops.
482 *
483 * There should _never_ be two instances of the same Proxy-State in the packet.
484 */
485 if ((inst->mode == RLM_RADIUS_MODE_PROXY) && RDEBUG_ENABLED) {
486 unsigned int count = 0;
487 fr_dcursor_t cursor;
488
489 for (vp = fr_pair_dcursor_by_da_init(&cursor, &request->request_pairs, attr_proxy_state);
490 vp;
491 vp = fr_dcursor_next(&cursor)) {
492 if (vp->vp_length != sizeof(inst->common_ctx.proxy_state)) continue;
493
494 if (memcmp(vp->vp_octets, &inst->common_ctx.proxy_state,
495 sizeof(inst->common_ctx.proxy_state)) == 0) {
496
497 /*
498 * Cancel proxying when there are two instances of the same Proxy-State
499 * in the packet. This limitation could be configurable, but it likely
500 * doesn't make sense to make it configurable.
501 */
502 if (count == 1) {
503 RWARN("Canceling proxy due to loop of multiple %pV", vp);
504 return -1;
505 }
506
507 RWARN("Proxied packet contains our own %pV", vp);
508 RWARN("Check if there is a proxy loop. Perhaps the server has been configured to proxy to itself.");
509 count++;
510 }
511 }
512 }
513
514 if (request->packet->code != FR_RADIUS_CODE_ACCESS_REQUEST) return 0;
515
516 if (fr_pair_find_by_da(&request->request_pairs, NULL, attr_chap_password) &&
517 !fr_pair_find_by_da(&request->request_pairs, NULL, attr_chap_challenge)) {
519 fr_pair_value_memdup(vp, request->packet->vector, sizeof(request->packet->vector), true);
520 }
521
522 return 0;
523}
524
525
526/** Send packets outbound.
527 *
528 */
529static unlang_action_t CC_HINT(nonnull) mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
530{
532 bio_thread_t *thread = talloc_get_type_abort(mctx->thread, bio_thread_t);
533 fr_client_t *client;
534 int rcode;
535 bio_request_t *u = NULL;
536 fr_retry_config_t const *retry_config = NULL;
537
538 if (!request->packet->code) {
539 REDEBUG("You MUST specify a packet code");
541 }
542
543 if ((request->packet->code >= FR_RADIUS_CODE_MAX) ||
544 !fr_time_delta_ispos(inst->retry[request->packet->code].irt)) { /* can't be zero */
545 REDEBUG("Invalid packet code %u", request->packet->code);
547 }
548
549 /*
550 * Unconnected sockets use %radius.replicate(ip, port, secret),
551 * or %radius.sendto(ip, port, secret)
552 */
554 (inst->mode == RLM_RADIUS_MODE_XLAT_PROXY)) {
555 REDEBUG("When using 'mode = unconnected-*', this module cannot be used in-place. Instead, it must be called via a function call");
557 }
558
559 client = client_from_request(request);
560 if (client && client->dynamic && !client->active) {
561 REDEBUG("Cannot proxy packets which define dynamic clients");
563 }
564
565 /*
566 * Push the request and it's data to the IO submodule.
567 *
568 * This may return YIELD, for "please yield", or it may
569 * return another code which indicates what happened to
570 * the request...
571 */
572 rcode = mod_enqueue(&u, &retry_config, inst, thread->ctx.trunk, request);
573 if (rcode == 0) RETURN_MODULE_NOOP;
574 if (rcode < 0) RETURN_MODULE_FAIL;
575
577}
578
579
580static int mod_instantiate(module_inst_ctx_t const *mctx)
581{
582 size_t i, num_types;
583 rlm_radius_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_radius_t);
584 CONF_SECTION *conf = mctx->mi->conf;
585
586 inst->name = mctx->mi->name;
587 inst->received_message_authenticator = talloc_zero(NULL, bool); /* Allocated outside of inst to default protection */
588
589 /*
590 * Allow explicit setting of mode.
591 */
592 if (inst->mode != RLM_RADIUS_MODE_INVALID) goto check_others;
593
594 /*
595 * If not set, try to insinuate it from context.
596 */
597 if (inst->replicate) {
598 if (inst->originate) {
599 cf_log_err(conf, "Cannot set 'replicate=true' and 'originate=true' at the same time.");
600 return -1;
601 }
602
603 if (inst->synchronous) {
604 cf_log_warn(conf, "Ignoring 'synchronous=true' due to 'replicate=true'");
605 }
606
608 goto check_others;
609 }
610
611 /*
612 * Argubly we should be allowed to do synchronous proxying _and_ originating client packets.
613 *
614 * However, the previous code didn't really do that consistently.
615 */
616 if (inst->synchronous && inst->originate) {
617 cf_log_err(conf, "Cannot set 'synchronous=true' and 'originate=true'");
618 return -1;
619 }
620
621 if (inst->synchronous) {
623 } else {
625 }
626
627check_others:
628 /*
629 * Replication is write-only, and append by default.
630 */
631 if (inst->mode == RLM_RADIUS_MODE_REPLICATE) {
632 if (inst->fd_config.filename && (inst->fd_config.flags != O_WRONLY)) {
633 cf_log_info(conf, "Setting 'flags = write-only' for writing to a file");
634 }
635 inst->fd_config.flags = O_WRONLY | O_APPEND;
636
637 } else if (inst->fd_config.filename) {
638 cf_log_err(conf, "When using an output 'filename', you MUST set 'mode = replicate'");
639 return -1;
640
641 } else {
642 /*
643 * All other IO is read+write.
644 */
645 inst->fd_config.flags = O_RDWR;
646 }
647
648 if (fr_bio_fd_check_config(&inst->fd_config) < 0) {
649 cf_log_perr(conf, "Invalid configuration");
650 return -1;
651 }
652
653 /*
654 * Clamp max_packet_size first before checking recv_buff and send_buff
655 */
656 FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, >=, 64);
657 FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, <=, 65535);
658
660 /*
661 * These limits are specific to RADIUS, and cannot be over-ridden
662 */
663 FR_INTEGER_BOUND_CHECK("trunk.per_connection_max", inst->trunk_conf.max_req_per_conn, >=, 2);
664 FR_INTEGER_BOUND_CHECK("trunk.per_connection_max", inst->trunk_conf.max_req_per_conn, <=, 255);
665 FR_INTEGER_BOUND_CHECK("trunk.per_connection_target", inst->trunk_conf.target_req_per_conn, <=, inst->trunk_conf.max_req_per_conn / 2);
666 }
667
669 (inst->mode == RLM_RADIUS_MODE_XLAT_PROXY)) {
670 if (inst->fd_config.src_port != 0) {
671 cf_log_err(conf, "Cannot set 'src_port' when using this 'mode'");
672 return -1;
673 }
674 }
675
676 FR_TIME_DELTA_BOUND_CHECK("response_window", inst->zombie_period, >=, fr_time_delta_from_sec(1));
677 FR_TIME_DELTA_BOUND_CHECK("response_window", inst->zombie_period, <=, fr_time_delta_from_sec(120));
678
679 FR_TIME_DELTA_BOUND_CHECK("zombie_period", inst->zombie_period, >=, fr_time_delta_from_sec(1));
680 FR_TIME_DELTA_BOUND_CHECK("zombie_period", inst->zombie_period, <=, fr_time_delta_from_sec(120));
681
682 if (!inst->status_check) {
683 FR_TIME_DELTA_BOUND_CHECK("revive_interval", inst->revive_interval, >=, fr_time_delta_from_sec(10));
684 FR_TIME_DELTA_BOUND_CHECK("revive_interval", inst->revive_interval, <=, fr_time_delta_from_sec(3600));
685 }
686
687 num_types = talloc_array_length(inst->types);
688 fr_assert(num_types > 0);
689
690 inst->timeout_retry = (fr_retry_config_t) {
691 .mrc = 1,
692 .mrd = inst->response_window,
693 };
694
695 inst->common_ctx = (fr_radius_ctx_t) {
696 .secret = inst->secret,
697 .secret_length = inst->secret ? talloc_array_length(inst->secret) - 1 : 0,
698 .proxy_state = ((uint64_t) fr_rand()) << 32 | fr_rand(),
699 };
700
701 /*
702 * Allow for O(1) lookup later...
703 */
704 for (i = 0; i < num_types; i++) {
705 uint32_t code;
706
707 code = inst->types[i];
708 fr_assert(code > 0);
710
711 inst->allowed[code] = true;
712 }
713
714 fr_assert(inst->status_check < FR_RADIUS_CODE_MAX);
715
716 /*
717 * If we're replicating, we don't care if the other end
718 * is alive.
719 */
720 if (inst->status_check) {
721 if (inst->mode == RLM_RADIUS_MODE_REPLICATE) {
722 cf_log_warn(conf, "Ignoring 'status_check = %s' due to 'mode = replicate'",
723 fr_radius_packet_name[inst->status_check]);
724 inst->status_check = false;
725
726 } else if ((inst->mode == RLM_RADIUS_MODE_UNCONNECTED_REPLICATE) ||
727 (inst->mode == RLM_RADIUS_MODE_XLAT_PROXY)) {
728 cf_log_warn(conf, "Ignoring 'status_check = %s' due to 'mode' setting",
729 fr_radius_packet_name[inst->status_check]);
730 inst->status_check = false;
731 }
732 }
733
734 /*
735 * If we have status checks, then do some sanity checks.
736 * Status-Server is always allowed. Otherwise, the
737 * status checks have to match one of the allowed
738 * packets.
739 */
740 if (inst->status_check) {
741 if (inst->status_check == FR_RADIUS_CODE_STATUS_SERVER) {
742 inst->allowed[inst->status_check] = true;
743
744 } else if (!inst->allowed[inst->status_check]) {
745 cf_log_err(conf, "Using 'status_check = %s' requires also 'type = %s'",
746 fr_radius_packet_name[inst->status_check], fr_radius_packet_name[inst->status_check]);
747 return -1;
748 }
749
750 /*
751 * @todo - check the contents of the "update"
752 * section, to be sure that (e.g.) Access-Request
753 * contains User-Name, etc.
754 */
755
756 if (inst->fd_config.filename) {
757 cf_log_info(conf, "Disabling status checks for output file %s", inst->fd_config.filename);
758 inst->status_check = 0;
759 }
760 }
761
762 /*
763 * Files and unix sockets can just have us call write().
764 */
765 if (inst->fd_config.filename || inst->fd_config.path) {
766 inst->max_send_coalesce = 1;
767 }
768
769 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 */
770 inst->trunk_conf.req_pool_size = 1024 + sizeof(fr_pair_t) + 20;
771
772 /*
773 * Only check the async timers when we're acting as a client.
774 */
775 if (inst->mode != RLM_RADIUS_MODE_CLIENT) {
776 return 0;
777 }
778
779 /*
780 * Set limits on retransmission timers
781 */
782 if (inst->allowed[FR_RADIUS_CODE_ACCESS_REQUEST]) {
783 FR_TIME_DELTA_BOUND_CHECK("Access-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].irt, >=, fr_time_delta_from_sec(1));
784 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
785 FR_INTEGER_BOUND_CHECK("Access-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrc, >=, 1);
786 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrd, >=, fr_time_delta_from_sec(5));
787
788 FR_TIME_DELTA_BOUND_CHECK("Access-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].irt, <=, fr_time_delta_from_sec(3));
789 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrt, <=, fr_time_delta_from_sec(30));
790 FR_INTEGER_BOUND_CHECK("Access-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrc, <=, 10);
791 FR_TIME_DELTA_BOUND_CHECK("Access-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCESS_REQUEST].mrd, <=, fr_time_delta_from_sec(30));
792 }
793
794 /*
795 * Note that RFC 5080 allows for Accounting-Request to
796 * have mrt=mrc=mrd = 0, which means "retransmit
797 * forever". We allow that, with the restriction that
798 * the server core will automatically free the request at
799 * max_request_time.
800 */
802 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].irt, >=, fr_time_delta_from_sec(1));
803#if 0
804 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
805 FR_INTEGER_BOUND_CHECK("Accounting-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrc, >=, 0);
806 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrd, >=, fr_time_delta_from_sec(0));
807#endif
808
809 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].irt, <=, fr_time_delta_from_sec(3));
810 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrt, <=, fr_time_delta_from_sec(30));
811 FR_INTEGER_BOUND_CHECK("Accounting-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrc, <=, 10);
812 FR_TIME_DELTA_BOUND_CHECK("Accounting-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_ACCOUNTING_REQUEST].mrd, <=, fr_time_delta_from_sec(30));
813 }
814
815 /*
816 * Status-Server
817 */
818 if (inst->allowed[FR_RADIUS_CODE_STATUS_SERVER]) {
819 FR_TIME_DELTA_BOUND_CHECK("Status-Server.initial_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].irt, >=, fr_time_delta_from_sec(1));
820 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrt, >=, fr_time_delta_from_sec(5));
821 FR_INTEGER_BOUND_CHECK("Status-Server.max_rtx_count", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrc, >=, 1);
822 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_duration", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrd, >=, fr_time_delta_from_sec(5));
823
824 FR_TIME_DELTA_BOUND_CHECK("Status-Server.initial_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].irt, <=, fr_time_delta_from_sec(3));
825 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_time", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrt, <=, fr_time_delta_from_sec(30));
826 FR_INTEGER_BOUND_CHECK("Status-Server.max_rtx_count", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrc, <=, 10);
827 FR_TIME_DELTA_BOUND_CHECK("Status-Server.max_rtx_duration", inst->retry[FR_RADIUS_CODE_STATUS_SERVER].mrd, <=, fr_time_delta_from_sec(30));
828 }
829
830 /*
831 * CoA
832 */
833 if (inst->allowed[FR_RADIUS_CODE_COA_REQUEST]) {
834 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].irt, >=, fr_time_delta_from_sec(1));
835 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
836 FR_INTEGER_BOUND_CHECK("CoA-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrc, >=, 1);
837 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrd, >=, fr_time_delta_from_sec(5));
838
839 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].irt, <=, fr_time_delta_from_sec(3));
840 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrt, <=, fr_time_delta_from_sec(60));
841 FR_INTEGER_BOUND_CHECK("CoA-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrc, <=, 10);
842 FR_TIME_DELTA_BOUND_CHECK("CoA-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_COA_REQUEST].mrd, <=, fr_time_delta_from_sec(30));
843 }
844
845 /*
846 * Disconnect
847 */
849 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].irt, >=, fr_time_delta_from_sec(1));
850 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrt, >=, fr_time_delta_from_sec(5));
851 FR_INTEGER_BOUND_CHECK("Disconnect-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrc, >=, 1);
852 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrd, >=, fr_time_delta_from_sec(5));
853
854 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.initial_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].irt, <=, fr_time_delta_from_sec(3));
855 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_time", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrt, <=, fr_time_delta_from_sec(30));
856 FR_INTEGER_BOUND_CHECK("Disconnect-Request.max_rtx_count", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrc, <=, 10);
857 FR_TIME_DELTA_BOUND_CHECK("Disconnect-Request.max_rtx_duration", inst->retry[FR_RADIUS_CODE_DISCONNECT_REQUEST].mrd, <=, fr_time_delta_from_sec(30));
858 }
859
860 return 0;
861}
862
863static int mod_bootstrap(module_inst_ctx_t const *mctx)
864{
865 xlat_t *xlat;
866 rlm_radius_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_radius_t);
867
868 switch (inst->mode) {
870 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "sendto.ipaddr", xlat_radius_replicate, FR_TYPE_VOID);
872 break;
873
875 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "sendto.ipaddr", xlat_radius_client, FR_TYPE_UINT32);
877 break;
878
879 default:
880 break;
881 }
882
883 return 0;
884}
885
886
887static int mod_detach(module_detach_ctx_t const *mctx)
888{
889 rlm_radius_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_radius_t);
890
891 talloc_free(inst->received_message_authenticator);
892 return 0;
893}
894
895static int mod_load(void)
896{
897 if (fr_radius_global_init() < 0) {
898 PERROR("Failed initialising protocol library");
899 return -1;
900 }
901 return 0;
902}
903
904static void mod_unload(void)
905{
907}
908
909/*
910 * The module name should be the only globally exported symbol.
911 * That is, everything else should be 'static'.
912 *
913 * If the module needs to temporarily modify it's instantiation
914 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
915 * The server will then take care of ensuring that the module
916 * is single-threaded.
917 */
920 .common = {
921 .magic = MODULE_MAGIC_INIT,
922 .name = "radius",
923 .inst_size = sizeof(rlm_radius_t),
925
926 .onload = mod_load,
927 .unload = mod_unload,
928
929 .bootstrap = mod_bootstrap,
931 .detach = mod_detach,
932
933 .thread_inst_size = sizeof(bio_thread_t),
934 .thread_inst_type = "bio_thread_t",
935 .thread_instantiate = mod_thread_instantiate,
936 },
937 .method_group = {
938 .bindings = (module_method_binding_t[]){
939 { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_process },
941 },
942 }
943};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define RCSID(id)
Definition build.h:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define STRINGIFY(x)
Definition build.h:197
#define UNUSED
Definition build.h:315
#define NUM_ELEMENTS(_t)
Definition build.h:337
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:1550
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:596
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:502
#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:268
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:581
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:674
#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:323
#define cf_section_rule_push(_cs, _rule)
Definition cf_parse.h:672
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:256
#define FR_CONF_OFFSET_REF(_struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition cf_parse.h:310
#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:297
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:513
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:418
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:432
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
Definition cf_parse.h:416
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:433
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
Definition cf_parse.h:444
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
#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:241
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
Common header for all CONF_* types.
Definition cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1185
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1171
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:684
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:618
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:664
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_log_info(_cf, _fmt,...)
Definition cf_util.h:291
#define cf_parent(_cf)
Definition cf_util.h:101
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:296
#define cf_log_warn(_cf, _fmt,...)
Definition cf_util.h:290
#define CF_IDENT_ANY
Definition cf_util.h:78
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:36
@ 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 ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:231
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3395
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
Value of an enumerated attribute.
Definition dict.h:227
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
Definition fd.h:68
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition fd.h:65
const conf_parser_t fr_bio_fd_client_config[]
Definition fd_config.c:256
int fr_bio_fd_check_config(fr_bio_fd_config_t const *cfg)
Checks the configuration without modifying anything.
Definition fd_open.c:834
bool active
for dynamic clients
Definition client.h:119
bool dynamic
Whether the client was dynamically defined.
Definition client.h:118
Describes a host allowed to send packets to the server.
Definition client.h:80
#define PERROR(_fmt,...)
Definition log.h:228
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RWARN(fmt,...)
Definition log.h:297
int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *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:1014
talloc_free(reap)
@ 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:470
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:257
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:2276
static void mod_retry(module_ctx_t const *mctx, request_t *request, fr_retry_t const *retry)
Handle module retries.
Definition bio.c:1442
bio_handle_ctx_t ctx
for copying to bio_handle_t
Definition bio.c:58
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:2493
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:2643
trunk_t * trunk
trunk handler
Definition bio.c:51
static unlang_action_t mod_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, UNUSED request_t *request)
Resume execution of the request, returning the rcode set during trunk execution.
Definition bio.c:2185
static xlat_arg_parser_t const xlat_radius_send_args[]
Definition bio.c:2483
Connect request_t to local tracking structure.
Definition bio.c:114
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:2981
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:693
static const conf_parser_t config[]
Definition base.c:183
size_t fr_radius_require_ma_table_len
Definition base.c:90
int fr_radius_global_init(void)
Definition base.c:1218
void fr_radius_global_free(void)
Definition base.c:1241
fr_table_num_sorted_t const fr_radius_require_ma_table[]
Definition base.c:83
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Definition base.c:112
Functions to support RADIUS bio handlers.
#define fr_assert(_expr)
Definition rad_assert.h:38
static fr_bio_fd_config_t fd_config
static char * secret
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG_ENABLED()
Definition radclient.h:49
#define RADIUS_MAX_ATTRIBUTES
Definition radius.h:40
static rs_t * conf
Definition radsniff.c:53
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:105
#define RETURN_MODULE_NOOP
Definition rcode.h:62
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static conf_parser_t coa_config[]
Definition rlm_radius.c:84
static conf_parser_t disconnect_config[]
Definition rlm_radius.c:92
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)
Definition rlm_radius.c:887
static int mod_load(void)
Definition rlm_radius.c:895
static fr_dict_attr_t const * attr_packet_type
Definition rlm_radius.c:187
static fr_dict_attr_t const * attr_user_password
Definition rlm_radius.c:198
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Send packets outbound.
Definition rlm_radius.c:529
static fr_dict_attr_t const * attr_eap_message
Definition rlm_radius.c:194
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:124
static fr_dict_attr_t const * attr_chap_password
Definition rlm_radius.c:186
static fr_dict_t const * dict_radius
Definition rlm_radius.c:177
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_radius.c:863
static fr_dict_attr_t const * attr_chap_challenge
Definition rlm_radius.c:185
static conf_parser_t status_config[]
Definition rlm_radius.c:76
fr_dict_attr_autoload_t rlm_radius_dict_attr[]
Definition rlm_radius.c:201
static fr_dict_attr_t const * attr_extended_attribute_1
Definition rlm_radius.c:192
static fr_dict_attr_t const * attr_error_cause
Definition rlm_radius.c:190
static void mod_unload(void)
Definition rlm_radius.c:904
static fr_dict_attr_t const * attr_proxy_state
Definition rlm_radius.c:188
static int radius_fixups(rlm_radius_t const *inst, request_t *request)
Do any RADIUS-layer fixups for proxying.
Definition rlm_radius.c:465
static fr_dict_attr_t const * attr_nas_identifier
Definition rlm_radius.c:195
static conf_parser_t const type_interval_config[FR_RADIUS_CODE_MAX]
Definition rlm_radius.c:168
static conf_parser_t auth_config[]
Definition rlm_radius.c:60
static int mode_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
module_rlm_t rlm_radius
Definition rlm_radius.c:919
fr_dict_autoload_t rlm_radius_dict[]
Definition rlm_radius.c:180
static conf_parser_t const transport_config[]
Definition rlm_radius.c:100
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:196
static fr_dict_attr_t const * attr_event_timestamp
Definition rlm_radius.c:191
static conf_parser_t const status_check_update_config[]
Definition rlm_radius.c:48
static fr_dict_attr_t const * attr_response_length
Definition rlm_radius.c:197
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_radius.c:580
static conf_parser_t const status_check_config[]
Definition rlm_radius.c:41
static size_t mode_names_len
Definition rlm_radius.c:229
static fr_table_num_sorted_t mode_names[]
Definition rlm_radius.c:222
static conf_parser_t const module_config[]
Definition rlm_radius.c:135
static conf_parser_t const connected_config[]
Definition rlm_radius.c:109
static fr_dict_attr_t const * attr_message_authenticator
Definition rlm_radius.c:193
static conf_parser_t acct_config[]
Definition rlm_radius.c:68
struct rlm_radius_s rlm_radius_t
Definition rlm_radius.h:39
rlm_radius_mode_t
Definition rlm_radius.h:41
@ RLM_RADIUS_MODE_XLAT_PROXY
Definition rlm_radius.h:47
@ RLM_RADIUS_MODE_INVALID
Definition rlm_radius.h:42
@ RLM_RADIUS_MODE_PROXY
Definition rlm_radius.h:43
@ RLM_RADIUS_MODE_REPLICATE
Definition rlm_radius.h:45
@ RLM_RADIUS_MODE_UNCONNECTED_REPLICATE
Definition rlm_radius.h:46
@ RLM_RADIUS_MODE_CLIENT
Definition rlm_radius.h:44
static char const * name
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
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:40
char const * name
Instance name e.g. user_database.
Definition module.h:335
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
size_t inst_size
Size of the module's instance data.
Definition module.h:203
void * data
Module's instance data.
Definition module.h:271
void * boot
Data allocated during the boostrap phase.
Definition module.h:274
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:151
Named methods exported by a module.
Definition module.h:173
#define pair_append_request(_attr, _da)
Allocate and append a fr_pair_t to the request list.
Definition pair.h:37
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:344
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:341
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:1112
return count
Definition module.c:163
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:361
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.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:285
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:653
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:282
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_delta_ispos(_a)
Definition time.h:290
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
Definition trunk.c:315
static fr_slen_t head
Definition xlat.h:422
#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:628
struct value_pair_s fr_pair_t
Definition pair.h:48
static fr_slen_t parent
Definition pair.h:851
int nonnull(2, 5))
static size_t char ** out
Definition value.h:997
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:365