The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
base.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
5 * (at 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: 62f561c12cac67b51ec98695789b7f46a9367675 $
19 * @file src/process/radius/base.c
20 * @brief RADIUS process module
21 *
22 * @copyright 2021 The FreeRADIUS server project.
23 * @copyright 2021 Network RADIUS SAS (legal@networkradius.com)
24 */
25#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
26
27#include <freeradius-devel/radius/radius.h>
28
29#include <freeradius-devel/server/main_config.h>
30#include <freeradius-devel/server/module.h>
31#include <freeradius-devel/server/pair.h>
32#include <freeradius-devel/server/protocol.h>
33#include <freeradius-devel/server/state.h>
34#include <freeradius-devel/server/log.h>
35#include <freeradius-devel/unlang/xlat.h>
36
37#include <freeradius-devel/unlang/module.h>
38#include <freeradius-devel/unlang/interpret.h>
39#include <freeradius-devel/unlang/xlat_func.h>
40
41#include <freeradius-devel/util/debug.h>
42#include <freeradius-devel/util/pair.h>
43#include <freeradius-devel/util/value.h>
44
46static fr_dict_t const *dict_radius;
47
50 { .out = &dict_freeradius, .proto = "freeradius" },
51 { .out = &dict_radius, .proto = "radius" },
52 { NULL }
53};
54
59
69
72 { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
73 { .out = &attr_module_failure_message, .name = "Module-Failure-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
74 { .out = &attr_module_success_message, .name = "Module-Success-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
75 { .out = &attr_stripped_user_name, .name = "Stripped-User-Name", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
76
77 { .out = &attr_acct_status_type, .name = "Acct-Status-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
78 { .out = &attr_proxy_state, .name = "Proxy-State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
79 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
80 { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
81 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
82 { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius },
83
84 { .out = &attr_original_packet_code, .name = "Extended-Attribute-1.Original-Packet-Code", .type = FR_TYPE_UINT32, .dict = &dict_radius },
85 { .out = &attr_error_cause, .name = "Error-Cause", .type = FR_TYPE_UINT32, .dict = &dict_radius },
86
87 { .out = &attr_event_timestamp, .name = "Event-Timestamp", .type = FR_TYPE_DATE, .dict = &dict_radius },
88
89 { NULL }
90};
91
94
97 { .out = &enum_auth_type_accept, .name = "Accept", .attr = &attr_auth_type },
98 { .out = &enum_auth_type_reject, .name = "Reject", .attr = &attr_auth_type },
99 { NULL }
100};
101
102/*
103 * RADIUS state machine configuration
104 */
133
134typedef struct {
135 fr_time_delta_t session_timeout; //!< Maximum time between the last response and next request.
136 uint32_t max_session; //!< Maximum ongoing session allowed.
137
138 uint8_t state_server_id; //!< Sets a specific byte in the state to allow the
139 //!< authenticating server to be identified in packet
140 //!<captures.
141
142 fr_state_tree_t *state_tree; //!< State tree to link multiple requests/responses.
144
145typedef struct {
146 CONF_SECTION *server_cs; //!< Our virtual server.
147 process_radius_sections_t sections; //!< Pointers to various config sections
148 ///< we need to execute.
149 process_radius_auth_t auth; //!< Authentication configuration.
151
152/** Records fields from the original request so we have a known good copy
153 */
154typedef struct {
155 fr_value_box_list_head_t proxy_state; //!< These need to be copied into the response in exactly
156 ///< the same order as they were added.
158
159#define FR_RADIUS_PROCESS_CODE_VALID(_x) (FR_RADIUS_PACKET_CODE_VALID(_x) || (_x == FR_RADIUS_CODE_DO_NOT_RESPOND))
160
161#define PROCESS_PACKET_TYPE fr_radius_packet_code_t
162#define PROCESS_CODE_MAX FR_RADIUS_CODE_MAX
163#define PROCESS_CODE_DO_NOT_RESPOND FR_RADIUS_CODE_DO_NOT_RESPOND
164#define PROCESS_PACKET_CODE_VALID FR_RADIUS_PROCESS_CODE_VALID
165#define PROCESS_INST process_radius_t
166#define PROCESS_CODE_DYNAMIC_CLIENT FR_RADIUS_CODE_ACCESS_ACCEPT
167#include <freeradius-devel/server/process.h>
168
170 { FR_CONF_OFFSET("timeout", process_radius_auth_t, session_timeout), .dflt = "15" },
171 { FR_CONF_OFFSET("max", process_radius_auth_t, max_session), .dflt = "4096" },
172 { FR_CONF_OFFSET("state_server_id", process_radius_auth_t, state_server_id) },
173
175};
176
177static const conf_parser_t auth_config[] = {
178 { FR_CONF_POINTER("session", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) session_config },
179
181};
182
183static const conf_parser_t config[] = {
184 { FR_CONF_POINTER("Access-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) auth_config,
185 .offset = offsetof(process_radius_t, auth), },
186
188};
189
190/*
191 * Debug the packet if requested.
192 */
193static void radius_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *list, bool received)
194{
195#ifdef WITH_IFINDEX_NAME_RESOLUTION
196 char if_name[IFNAMSIZ];
197#endif
198
199 if (!packet) return;
200 if (!RDEBUG_ENABLED) return;
201
202 log_request(L_DBG, L_DBG_LVL_1, request, __FILE__, __LINE__, "%s %s ID %d from %s%pV%s:%i to %s%pV%s:%i "
203#ifdef WITH_IFINDEX_NAME_RESOLUTION
204 "%s%s%s"
205#endif
206 "",
207 received ? "Received" : "Sending",
209 packet->id,
210 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
211 fr_box_ipaddr(packet->socket.inet.src_ipaddr),
212 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
213 packet->socket.inet.src_port,
214 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
215 fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
216 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
217 packet->socket.inet.dst_port
218#ifdef WITH_IFINDEX_NAME_RESOLUTION
219 , packet->socket.inet.ifindex ? "via " : "",
220 packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
221 packet->socket.inet.ifindex ? " " : ""
222#endif
223 );
224
225 if (received || request->parent) {
226 log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
227 } else {
228 log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
229 }
230}
231
232/** Keep a copy of some attributes to keep them from being tamptered with
233 *
234 */
235static inline CC_HINT(always_inline)
237{
238 fr_pair_t *proxy_state;
240
241 /*
242 * Don't bother allocing the struct if there's no proxy state to store
243 */
244 proxy_state = fr_pair_find_by_da(&request->request_pairs, NULL, attr_proxy_state);
245 if (!proxy_state) return 0;
246
248 fr_value_box_list_init(&rctx->proxy_state);
249
250 /*
251 * We don't use fr_pair_list_copy_by_da, to avoid doing the lookup for
252 * the first proxy-state attr again.
253 */
254 do {
255 fr_value_box_t *proxy_state_value;
256
257 MEM((proxy_state_value = fr_value_box_acopy(rctx, &proxy_state->data)));
258 fr_value_box_list_insert_tail(&rctx->proxy_state, proxy_state_value);
259 } while ((proxy_state = fr_pair_find_by_da(&request->request_pairs, proxy_state, attr_proxy_state)));
260
261 return rctx;
262}
263
264static inline CC_HINT(always_inline)
266{
267 if (!rctx) return;
268
269 /*
270 * Proxy-State is a link-level signal between RADIUS
271 * client and server. RFC 2865 Section 5.33 says that
272 * Proxy-State is an opaque field, and implementations
273 * most not examine it, interpret it, or assign it any
274 * meaning. Implementations must also copy all Proxy-State
275 * from the request to the reply.
276 *
277 * The rlm_radius module already deletes any Proxy-State
278 * from the reply before appending the proxy reply to the
279 * current reply.
280 *
281 * If any policy creates Proxy-State, that could affect
282 * individual RADIUS links (perhaps), and that would be
283 * wrong. As such, we nuke any nonsensical Proxy-State
284 * added by policies or errant modules, and instead just
285 * do exactly what the RFCs require us to do. No more.
286 */
287 fr_pair_delete_by_da(&request->reply_pairs, attr_proxy_state);
288
289 RDEBUG3("Adding Proxy-State attributes from request");
290 RINDENT();
291 fr_value_box_list_foreach(&rctx->proxy_state, proxy_state_value) {
292 fr_pair_t *vp;
293
294 MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_proxy_state));
295 fr_value_box_copy(vp, &vp->data, proxy_state_value);
296 fr_pair_append(&request->reply_pairs, vp);
297 RDEBUG3("&reply.%pP", vp);
298 }
299 REXDENT();
300}
301
302/** A wrapper around recv generic which stores fields from the request
303 */
304RECV(generic_radius_request)
305{
306 module_ctx_t our_mctx = *mctx;
307
308 fr_assert_msg(!mctx->rctx, "rctx not expected here");
309 our_mctx.rctx = radius_request_pairs_store(request);
310 mctx = &our_mctx; /* Our mutable mctx */
311
312 return CALL_RECV(generic);
313}
314
315/** A wrapper around send generic which restores fields
316 *
317 */
318RESUME(generic_radius_response)
319{
320 if (mctx->rctx) radius_request_pairs_to_reply(request, talloc_get_type_abort(mctx->rctx, process_radius_request_pairs_t));
321
322 return CALL_RESUME(send_generic);
323}
324
325RECV(access_request)
326{
328
329 /*
330 * Only reject if the state has already been thawed.
331 * It could be that the state value wasn't intended
332 * for us, and we're just proxying upstream.
333 */
334 if (fr_state_to_request(inst->auth.state_tree, request) < 0) {
335 return CALL_SEND_TYPE(FR_RADIUS_CODE_ACCESS_REJECT);
336 }
337
338 return CALL_RECV(generic_radius_request);
339}
340
341RESUME(auth_type);
342
343RESUME(access_request)
344{
345 rlm_rcode_t rcode = *p_result;
346 fr_pair_t *vp;
347 CONF_SECTION *cs;
348 fr_dict_enum_value_t const *dv;
349 fr_process_state_t const *state;
351
353
355
356 /*
357 * See if the return code from "recv Access-Request" says we reject, or continue.
358 */
359 UPDATE_STATE(packet);
360
361 request->reply->code = state->packet_type[rcode];
362 if (!request->reply->code) request->reply->code = state->default_reply;
363
364 /*
365 * Something set reject, we're done.
366 */
367 if (request->reply->code == FR_RADIUS_CODE_ACCESS_REJECT) {
368 RDEBUG("The 'recv Access-Request' section returned %s - rejecting the request",
369 fr_table_str_by_value(rcode_table, rcode, "<INVALID>"));
370
372 UPDATE_STATE(reply);
373
374 fr_assert(state->send != NULL);
375 return CALL_SEND_STATE(state);
376 }
377
378 if (request->reply->code) {
379 goto send_reply;
380 }
381
382 /*
383 * A policy _or_ a module can hard-code the reply.
384 */
385 if (!request->reply->code) {
386 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_packet_type);
387 if (vp && FR_RADIUS_PROCESS_CODE_VALID(vp->vp_uint32)) {
388 request->reply->code = vp->vp_uint32;
389 goto send_reply;
390 }
391 }
392
393 /*
394 * Run authenticate foo { ... }
395 *
396 * If we can't find Auth-Type, OR if we can't find
397 * Auth-Type = foo, then it's a reject.
398 */
399 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_auth_type);
400 if (!vp) {
401 RDEBUG("No 'Auth-Type' attribute found, cannot authenticate the user - rejecting the request");
402
403 reject:
404 request->reply->code = FR_RADIUS_CODE_ACCESS_REJECT;
405 goto send_reply;
406 }
407
408 dv = fr_dict_enum_by_value(vp->da, &vp->data);
409 if (!dv) {
410 RDEBUG("Invalid value for 'Auth-Type' attribute, cannot authenticate the user - rejecting the request");
411
412 goto reject;
413 }
414
415 /*
416 * The magic Auth-Type Accept value
417 * which means skip the authenticate
418 * section.
419 *
420 * And Reject means always reject. Tho the admin should
421 * just return "reject" from the section.
422 */
424 request->reply->code = FR_RADIUS_CODE_ACCESS_ACCEPT;
425 goto send_reply;
426
427 } else if (fr_value_box_cmp(enum_auth_type_reject, dv->value) == 0) {
428 request->reply->code = FR_RADIUS_CODE_ACCESS_REJECT;
429 goto send_reply;
430 }
431
432 cs = cf_section_find(inst->server_cs, "authenticate", dv->name);
433 if (!cs) {
434 RDEBUG2("No 'authenticate %s { ... }' section found - rejecting the request", dv->name);
435 goto reject;
436 }
437
438 /*
439 * Run the "Authenticate = foo" section.
440 *
441 * And continue with sending the generic reply.
442 */
443 RDEBUG("Running 'authenticate %s' from file %s", cf_section_name2(cs), cf_filename(cs));
444 return unlang_module_yield_to_section(p_result, request,
445 cs, RLM_MODULE_NOOP, resume_auth_type,
446 NULL, 0, mctx->rctx);
447}
448
449RESUME(auth_type)
450{
451 static const fr_process_rcode_t auth_type_rcode = {
460 };
461
462 rlm_rcode_t rcode = *p_result;
463 fr_pair_t *vp;
464 fr_process_state_t const *state;
465
467
469
470 if (auth_type_rcode[rcode] == FR_RADIUS_CODE_DO_NOT_RESPOND) {
471 request->reply->code = auth_type_rcode[rcode];
472 UPDATE_STATE(reply);
473
474 RDEBUG("The 'authenticate' section returned %s - not sending a response",
475 fr_table_str_by_value(rcode_table, rcode, "<INVALID>"));
476
477 fr_assert(state->send != NULL);
478 return state->send(p_result, mctx, request);
479 }
480
481 /*
482 * Most cases except handled...
483 */
484 if (auth_type_rcode[rcode]) request->reply->code = auth_type_rcode[rcode];
485
486 switch (request->reply->code) {
487 case 0:
488 RDEBUG("No reply code was set. Forcing to Access-Reject");
489 request->reply->code = FR_RADIUS_CODE_ACCESS_REJECT;
491
492 /*
493 * Print complaints before running "send Access-Reject"
494 */
496 RDEBUG2("Failed to authenticate the user");
497
498 /*
499 * Maybe the shared secret is wrong?
500 */
501 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_password);
502 if (vp) {
503 if (RDEBUG_ENABLED2) {
504 uint8_t const *p;
505
506 p = (uint8_t const *) vp->vp_strvalue;
507 while (*p) {
508 int size;
509
510 size = fr_utf8_char(p, -1);
511 if (!size) {
512 RWDEBUG("Unprintable characters in the password. "
513 "Double-check the shared secret on the server "
514 "and the NAS!");
515 break;
516 }
517 p += size;
518 }
519 }
520 }
521 break;
522
523 /*
524 * Access-Challenge sections require a State. If there is
525 * none, create one here. This is so that the State
526 * attribute is accessible in the "send Access-Challenge"
527 * section.
528 */
530 if ((vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_state)) != NULL) {
531 uint8_t buffer[16];
532
533 fr_rand_buffer(buffer, sizeof(buffer));
534
536 fr_pair_value_memdup(vp, buffer, sizeof(buffer), false);
537 }
538 break;
539
540 default:
541 break;
542
543 }
544 UPDATE_STATE(reply);
545
546 fr_assert(state->send != NULL);
547 return state->send(p_result, mctx, request);
548}
549
550RESUME(access_accept)
551{
552 fr_pair_t *vp;
554
556
557 /*
558 * Check that there is a name which can be used to
559 * identify the user. The configuration depends on
560 * User-Name or Stripped-User-Name existing, and being
561 * (mostly) unique to that user.
562 */
563 if (!request->parent &&
564 ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_name)) != NULL) &&
565 (vp->vp_strvalue[0] == '@') &&
566 !fr_pair_find_by_da(&request->request_pairs, NULL, attr_stripped_user_name)) {
567 RWDEBUG("User-Name is anonymized, and no Stripped-User-Name exists.");
568 RWDEBUG("It may be difficult or impossible to identify the user.");
569 RWDEBUG("Please update Stripped-User-Name with information which identifies the user.");
570 }
571
572 fr_state_discard(inst->auth.state_tree, request);
573 radius_request_pairs_to_reply(request, mctx->rctx);
575}
576
577RESUME(access_reject)
578{
580
582
583 fr_state_discard(inst->auth.state_tree, request);
584 radius_request_pairs_to_reply(request, mctx->rctx);
586}
587
588RESUME(access_challenge)
589{
591
593
594 /*
595 * Cache the state context, unless this is a subrequest.
596 * Subrequest state context will be handled by the caller.
597 *
598 * If this fails, don't respond to the request.
599 */
600 if (!request->parent && fr_request_to_state(inst->auth.state_tree, request) < 0) {
601 return CALL_SEND_TYPE(FR_RADIUS_CODE_DO_NOT_RESPOND);
602 }
603
604 fr_assert(request->reply->code == FR_RADIUS_CODE_ACCESS_CHALLENGE);
605 radius_request_pairs_to_reply(request, mctx->rctx);
607}
608
609/** A wrapper around recv generic which stores fields from the request
610 */
611RECV(accounting_request)
612{
613 module_ctx_t our_mctx = *mctx;
614 fr_pair_t *acct_delay, *event_timestamp;
615
616 fr_assert_msg(!mctx->rctx, "rctx not expected here");
617 our_mctx.rctx = radius_request_pairs_store(request);
618 mctx = &our_mctx; /* Our mutable mctx */
619
620 /*
621 * Acct-Delay-Time is horrific. Its existence in a packet means that any retransmissions can't
622 * be retransmissions! Instead, we have to send a brand new packet each time. This rewriting is
623 * expensive, causes ID churn, over-allocation of IDs, and makes it more difficult to discover
624 * end-to-end failures.
625 *
626 * As a result, we delete Acct-Delay-Time, and replace it with Event-Timestamp.
627 */
628 event_timestamp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_event_timestamp);
629 if (!event_timestamp) {
630 MEM(event_timestamp = fr_pair_afrom_da(request->request_ctx, attr_event_timestamp));
631 fr_pair_append(&request->request_pairs, event_timestamp);
632 event_timestamp->vp_date = fr_time_to_unix_time(request->packet->timestamp);
633
634 acct_delay = fr_pair_find_by_da(&request->request_pairs, NULL, attr_event_timestamp);
635 if (acct_delay) {
636 if (acct_delay->vp_uint32 < ((365 * 86400))) {
637 event_timestamp->vp_date = fr_unix_time_sub_time_delta(event_timestamp->vp_date, fr_time_delta_from_sec(acct_delay->vp_uint32));
638
639 RDEBUG("Accounting-Request packet contains %pP. Creating %pP",
640 acct_delay, event_timestamp);
641 }
642 } else {
643 RDEBUG("Accounting-Request packet is missing Event-Timestamp. Adding it to packet as %pP.", event_timestamp);
644 }
645 }
646
647 return CALL_RECV(generic);
648}
649
650RESUME(acct_type)
651{
652 static const fr_process_rcode_t acct_type_rcode = {
658 };
659
660 rlm_rcode_t rcode = *p_result;
661 fr_process_state_t const *state;
662
664
666 fr_assert(FR_RADIUS_PROCESS_CODE_VALID(request->reply->code));
667
668 if (acct_type_rcode[rcode]) {
669 fr_assert(acct_type_rcode[rcode] == FR_RADIUS_CODE_DO_NOT_RESPOND);
670
671 request->reply->code = acct_type_rcode[rcode];
672 UPDATE_STATE(reply);
673
674 RDEBUG("The 'accounting' section returned %s - not sending a response",
675 fr_table_str_by_value(rcode_table, rcode, "<INVALID>"));
676
677 fr_assert(state->send != NULL);
678 return state->send(p_result, mctx, request);
679 }
680
681 request->reply->code = FR_RADIUS_CODE_ACCOUNTING_RESPONSE;
682 UPDATE_STATE(reply);
683
684 fr_assert(state->send != NULL);
685 return state->send(p_result, mctx, request);
686}
687
688RESUME(accounting_request)
689{
690 rlm_rcode_t rcode = *p_result;
691 fr_pair_t *vp;
692 CONF_SECTION *cs;
693 fr_dict_enum_value_t const *dv;
694 fr_process_state_t const *state;
696
698
700
701 UPDATE_STATE(packet);
702 fr_assert(state->packet_type[rcode] != 0);
703
704 request->reply->code = state->packet_type[rcode];
705 UPDATE_STATE_CS(reply);
706
707 if (request->reply->code == FR_RADIUS_CODE_DO_NOT_RESPOND) {
708 RDEBUG("The 'recv Accounting-Request' section returned %s - not sending a response",
709 fr_table_str_by_value(rcode_table, rcode, "<INVALID>"));
710
712 fr_assert(state->send != NULL);
713 return CALL_SEND_STATE(state);
714 }
715
716 /*
717 * Run accounting foo { ... }
718 */
719 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_status_type);
720 if (!vp) goto send_reply;
721
722 dv = fr_dict_enum_by_value(vp->da, &vp->data);
723 if (!dv) goto send_reply;
724
725 cs = cf_section_find(inst->server_cs, "accounting", dv->name);
726 if (!cs) {
727 RDEBUG2("No 'accounting %s { ... }' section found - skipping...", dv->name);
728 goto send_reply;
729 }
730
731 /*
732 * Run the "Acct-Status-Type = foo" section.
733 *
734 * And continue with sending the generic reply.
735 */
736 return unlang_module_yield_to_section(p_result, request,
737 cs, RLM_MODULE_NOOP, resume_acct_type,
738 NULL, 0, mctx->rctx);
739}
740
741#if 0
742// @todo - send canned responses like in v3?
743RECV(status_server)
744{
746}
747
748RESUME(status_server)
749{
751}
752#endif
753
754RESUME(protocol_error)
755{
756 fr_pair_t *vp;
757
759
760 fr_assert(FR_RADIUS_PACKET_CODE_VALID(request->reply->code));
761
762 /*
763 * https://tools.ietf.org/html/rfc7930#section-4
764 */
765 vp = fr_pair_find_by_da_nested(&request->reply_pairs, NULL, attr_original_packet_code);
766 if (!vp) {
767 vp = fr_pair_afrom_da(request->reply_ctx, attr_original_packet_code);
768 if (vp) {
769 vp->vp_uint32 = request->packet->code;
770 fr_pair_append(&request->reply_pairs, vp);
771 }
772 }
773
774 /*
775 * If there's no Error-Cause, then include a generic 404.
776 */
777 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_error_cause);
778 if (!vp) {
779 vp = fr_pair_afrom_da(request->reply_ctx, attr_error_cause);
780 if (vp) {
781 vp->vp_uint32 = FR_ERROR_CAUSE_VALUE_INVALID_REQUEST;
782 fr_pair_append(&request->reply_pairs, vp);
783 }
784 }
785
786 /*
787 * And do the generic processing after running a "send" section.
788 */
789 return CALL_RESUME(send_generic);
790}
791
792static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
793{
794 fr_process_state_t const *state;
795
797
799
800 request->component = "radius";
801 request->module = NULL;
802 fr_assert(request->dict == dict_radius);
803
804 fr_assert(FR_RADIUS_PACKET_CODE_VALID(request->packet->code));
805
806 UPDATE_STATE(packet);
807
808 if (!state->recv) {
809 REDEBUG("Invalid packet type (%u)", request->packet->code);
811 }
812
813 radius_packet_debug(request, request->packet, &request->request_pairs, true);
814
815 if (unlikely(request_is_dynamic_client(request))) {
816 return new_client(p_result, mctx, request);
817 }
818
819 return state->recv(p_result, mctx, request);
820}
821
823 { .required = true, .single = true, .type = FR_TYPE_OCTETS },
825};
826
827/** Validates a request against a know shared secret
828 *
829 * Designed for the specific purpose of verifying dynamic clients
830 * against a know shared secret.
831 *
832 * Example:
833@verbatim
834%radius.secret.verify(<secret>)
835@endverbatim
836 *
837 * @ingroup xlat_functions
838 */
840 request_t *request, fr_value_box_list_t *args)
841{
843 int ret;
844 bool require_message_authenticator = false;
845
847
848 if (request->dict != dict_radius) return XLAT_ACTION_FAIL;
849
850 MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL));
851
852 /*
853 * Only Access-Requests require a Message-Authenticator.
854 * All the other packet types are signed using the
855 * authenticator field.
856 */
857 if (request->packet->code == FR_RADIUS_CODE_ACCESS_REQUEST) require_message_authenticator = true;
858
859 ret = fr_radius_verify(request->packet->data, NULL, secret->vb_octets, secret->vb_length, require_message_authenticator, false);
860 switch (ret) {
861 case 0:
862 vb->vb_bool = true;
863 break;
864
865 case -1:
866 RPEDEBUG("Failed verifying secret");
867 return XLAT_ACTION_FAIL;
868
869 case -2:
870 RPDEBUG2("Provided secret was not used to sign this packet");
871 vb->vb_bool = false;
872 break;
873 }
875
876 return XLAT_ACTION_DONE;
877}
878
879static int mod_instantiate(module_inst_ctx_t const *mctx)
880{
881 process_radius_t *inst = talloc_get_type_abort(mctx->mi->data, process_radius_t);
882
883 inst->server_cs = cf_item_to_section(cf_parent(mctx->mi->conf));
884
885 inst->auth.state_tree = fr_state_tree_init(inst, attr_state, main_config->spawn_workers, inst->auth.max_session,
886 inst->auth.session_timeout, inst->auth.state_server_id,
888
889 return 0;
890}
891
892static int mod_bootstrap(module_inst_ctx_t const *mctx)
893{
894 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(mctx->mi->conf));
895
896 if (virtual_server_section_attribute_define(server_cs, "authenticate", attr_auth_type) < 0) return -1;
897
898 return 0;
899}
900
901static int mod_load(void)
902{
903 xlat_t *xlat;
904
905 if (unlikely(!(xlat = xlat_func_register(NULL, "radius.secret.verify", xlat_func_radius_secret_verify,
906 FR_TYPE_BOOL)))) return -1;
907
909
910 return 0;
911}
912
913static void mod_unload(void)
914{
915 xlat_func_unregister("radius.secret.verify");
916}
917
918/*
919 * rcodes not listed under a packet_type
920 * mean that the packet code will not be
921 * changed.
922 */
923static fr_process_state_t const process_state[] = {
925 .packet_type = {
931 },
932 .rcode = RLM_MODULE_NOOP,
933 .recv = recv_access_request,
934 .resume = resume_access_request,
935 .section_offset = offsetof(process_radius_sections_t, access_request),
936 },
938 .packet_type = {
943 },
944 .rcode = RLM_MODULE_NOOP,
945 .send = send_generic,
946 .resume = resume_access_accept,
947 .section_offset = offsetof(process_radius_sections_t, access_accept),
948 },
950 .packet_type = {
955 },
956 .rcode = RLM_MODULE_NOOP,
957 .send = send_generic,
958 .resume = resume_access_reject,
959 .section_offset = offsetof(process_radius_sections_t, access_reject),
960 },
962 .packet_type = {
967 },
968 .rcode = RLM_MODULE_NOOP,
969 .send = send_generic,
970 .resume = resume_access_challenge,
971 .section_offset = offsetof(process_radius_sections_t, access_challenge),
972 },
973
975 .packet_type = {
980
986 },
987 .rcode = RLM_MODULE_NOOP,
988 .recv = recv_accounting_request,
989 .resume = resume_accounting_request,
990 .section_offset = offsetof(process_radius_sections_t, accounting_request),
991 },
993 .packet_type = {
999 },
1000 .rcode = RLM_MODULE_NOOP,
1001 .send = send_generic,
1002 .resume = resume_generic_radius_response,
1003 .section_offset = offsetof(process_radius_sections_t, accounting_response),
1004 },
1005 [ FR_RADIUS_CODE_STATUS_SERVER ] = { /* @todo - negotiation, stats, etc. */
1006 .packet_type = {
1009
1016 },
1017 .rcode = RLM_MODULE_NOOP,
1018 .recv = recv_generic,
1019 .resume = resume_recv_generic,
1020 .section_offset = offsetof(process_radius_sections_t, status_server),
1021 },
1023 .packet_type = {
1028
1033 },
1034 .rcode = RLM_MODULE_NOOP,
1035 .recv = recv_generic_radius_request,
1036 .resume = resume_recv_generic,
1037 .section_offset = offsetof(process_radius_sections_t, coa_request),
1038 },
1040 .packet_type = {
1045 },
1046 .rcode = RLM_MODULE_NOOP,
1047 .send = send_generic,
1048 .resume = resume_generic_radius_response,
1049 .section_offset = offsetof(process_radius_sections_t, coa_ack),
1050 },
1052 .packet_type = {
1057 },
1058 .rcode = RLM_MODULE_NOOP,
1059 .send = send_generic,
1060 .resume = resume_generic_radius_response,
1061 .section_offset = offsetof(process_radius_sections_t, coa_nak),
1062 },
1064 .packet_type = {
1069
1074 },
1075 .rcode = RLM_MODULE_NOOP,
1076 .recv = recv_generic,
1077 .resume = resume_recv_generic,
1078 .section_offset = offsetof(process_radius_sections_t, disconnect_request),
1079 },
1081 .packet_type = {
1086 },
1087 .rcode = RLM_MODULE_NOOP,
1088 .send = send_generic,
1089 .resume = resume_generic_radius_response,
1090 .section_offset = offsetof(process_radius_sections_t, disconnect_ack),
1091 },
1093 .packet_type = {
1098 },
1099 .rcode = RLM_MODULE_NOOP,
1100 .send = send_generic,
1101 .resume = resume_generic_radius_response,
1102 .section_offset = offsetof(process_radius_sections_t, disconnect_nak),
1103 },
1104 [ FR_RADIUS_CODE_PROTOCOL_ERROR ] = { /* @todo - fill out required fields */
1105 .packet_type = {
1110 },
1111 .rcode = RLM_MODULE_NOOP,
1112 .send = send_generic,
1113 .resume = resume_protocol_error,
1114 .section_offset = offsetof(process_radius_sections_t, protocol_error),
1115 },
1117 .packet_type = {
1122
1128 },
1129 .rcode = RLM_MODULE_NOOP,
1130 .send = send_generic,
1131 .resume = resume_send_generic,
1132 .section_offset = offsetof(process_radius_sections_t, do_not_respond),
1133 }
1134};
1135
1137 {
1138 .section = SECTION_NAME("recv", "Access-Request"),
1139 .actions = &mod_actions_authorize,
1140 .offset = PROCESS_CONF_OFFSET(access_request),
1141 },
1142 {
1143 .section = SECTION_NAME("send", "Access-Accept"),
1145 .offset = PROCESS_CONF_OFFSET(access_accept),
1146 },
1147 {
1148 .section = SECTION_NAME("send", "Access-Challenge"),
1150 .offset = PROCESS_CONF_OFFSET(access_challenge),
1151 },
1152 {
1153 .section = SECTION_NAME("send", "Access-Reject"),
1155 .offset = PROCESS_CONF_OFFSET(access_reject),
1156 },
1157
1158 {
1159 .section = SECTION_NAME("recv", "Accounting-Request"),
1161 .offset = PROCESS_CONF_OFFSET(accounting_request),
1162 },
1163 {
1164 .section = SECTION_NAME("send", "Accounting-Response"),
1166 .offset = PROCESS_CONF_OFFSET(accounting_response),
1167 },
1168
1169 {
1170 .section = SECTION_NAME("recv", "Status-Server"),
1172 .offset = PROCESS_CONF_OFFSET(status_server),
1173 },
1174 {
1175 .section = SECTION_NAME("recv", "CoA-Request"),
1177 .offset = PROCESS_CONF_OFFSET(coa_request),
1178 },
1179 {
1180 .section = SECTION_NAME("send", "CoA-ACK"),
1182 .offset = PROCESS_CONF_OFFSET(coa_ack),
1183 },
1184 {
1185 .section = SECTION_NAME("send", "CoA-NAK"),
1187 .offset = PROCESS_CONF_OFFSET(coa_nak),
1188 },
1189 {
1190 .section = SECTION_NAME("recv", "Disconnect-Request"),
1192 .offset = PROCESS_CONF_OFFSET(disconnect_request),
1193 },
1194 {
1195 .section = SECTION_NAME("send", "Disconnect-ACK"),
1197 .offset = PROCESS_CONF_OFFSET(disconnect_ack),
1198 },
1199 {
1200 .section = SECTION_NAME("send", "Disconnect-NAK"),
1202 .offset = PROCESS_CONF_OFFSET(disconnect_nak),
1203 },
1204 {
1205 .section = SECTION_NAME("send", "Protocol-Error"),
1207 .offset = PROCESS_CONF_OFFSET(protocol_error),
1208 },
1209 {
1210 .section = SECTION_NAME("send", "Do-Not-Respond"),
1212 .offset = PROCESS_CONF_OFFSET(do_not_respond),
1213 },
1214 {
1215 .section = SECTION_NAME("authenticate", CF_IDENT_ANY),
1217 },
1218 {
1219 .section = SECTION_NAME("accounting", CF_IDENT_ANY),
1221 },
1222
1223 DYNAMIC_CLIENT_SECTIONS,
1224
1226};
1227
1230 .common = {
1231 .magic = MODULE_MAGIC_INIT,
1232 .name = "radius",
1233 .config = config,
1234 .inst_size = sizeof(process_radius_t),
1235
1236 .onload = mod_load,
1237 .unload = mod_unload,
1238 .bootstrap = mod_bootstrap,
1240 },
1241 .process = mod_process,
1242 .compile_list = compile_list,
1243 .dict = &dict_radius,
1244};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
static int const char char buffer[256]
Definition acutest.h:576
va_list args
Definition acutest.h:770
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:322
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#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
#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
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
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
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:1028
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:684
#define cf_parent(_cf)
Definition cf_util.h:101
#define cf_filename(_cf)
Definition cf_util.h:107
#define CF_IDENT_ANY
Definition cf_util.h:78
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:210
#define MEM(x)
Definition debug.h:36
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition defs.h:43
@ 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_DO_NOT_RESPOND
Special rcode to indicate we will not respond.
Definition defs.h:54
@ FR_RADIUS_CODE_DISCONNECT_ACK
RFC3575/RFC5176 - Disconnect-Ack (positive)
Definition defs.h:47
@ 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_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition defs.h:34
@ FR_RADIUS_CODE_ACCOUNTING_RESPONSE
RFC2866 - Accounting-Response.
Definition defs.h:37
@ FR_RADIUS_CODE_COA_NAK
RFC3575/RFC5176 - CoA-Nak (not willing to perform)
Definition defs.h:51
@ FR_RADIUS_CODE_COA_ACK
RFC3575/RFC5176 - CoA-Ack (positive)
Definition defs.h:50
@ FR_RADIUS_CODE_DISCONNECT_NAK
RFC3575/RFC5176 - Disconnect-Nak (not willing to perform)
Definition defs.h:48
@ FR_RADIUS_CODE_PROTOCOL_ERROR
RFC7930 - Protocol-Error (generic NAK)
Definition defs.h:52
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
Definition defs.h:36
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
Definition defs.h:35
fr_dict_enum_value_t * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
Definition dict_util.c:3349
fr_value_box_t const ** out
Enumeration value.
Definition dict.h:257
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
char const * name
Enum name.
Definition dict.h:228
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
Specifies a value which must be present for the module to function.
Definition dict.h:256
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
static xlat_action_t xlat_func_radius_secret_verify(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Validates a request against a know shared secret.
Definition base.c:839
uint32_t fr_hash_string(char const *p)
Definition hash.c:865
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition interpret.c:1403
static fr_dict_t const * dict_freeradius
Definition base.c:37
fr_dict_attr_t const * attr_packet_type
Definition base.c:93
fr_dict_attr_t const * attr_state
Definition base.c:103
fr_dict_t const * dict_radius
Definition base.c:78
fr_dict_attr_t const * attr_user_name
Definition base.c:104
void log_request_proto_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a list of protocol fr_pair_ts.
Definition log.c:854
void log_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt,...)
Marshal variadic log arguments into a va_list and pass to normal logging functions.
Definition log.c:612
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
Definition log.c:830
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:443
#define RPDEBUG2(fmt,...)
Definition log.h:347
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RDEBUG3(fmt,...)
Definition log.h:343
#define RPEDEBUG(fmt,...)
Definition log.h:376
#define RINDENT()
Indent R* messages by one level.
Definition log.h:430
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition log.h:70
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:59
main_config_t const * main_config
Main server configuration.
Definition main_config.c:69
bool spawn_workers
Should the server spawn threads.
Definition main_config.h:58
@ 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_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
unsigned char uint8_t
unlang_mod_actions_t const mod_actions_preacct
Definition mod_action.c:59
unlang_mod_actions_t const mod_actions_authenticate
Definition mod_action.c:29
unlang_mod_actions_t const mod_actions_accounting
Definition mod_action.c:74
unlang_mod_actions_t const mod_actions_authorize
Definition mod_action.c:44
unlang_mod_actions_t const mod_actions_postauth
Definition mod_action.c:88
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Definition mod_action.h:62
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * rctx
Resume ctx that a module previously set.
Definition module_ctx.h:45
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 instantiation calls.
Definition module_ctx.h:50
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_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition pair.c:770
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
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1345
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
Definition pair.c:1689
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:283
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition print.c:39
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition base.c:179
static const virtual_server_compile_t compile_list[]
Definition base.c:205
static fr_process_state_t const process_state[]
Definition base.c:68
static fr_dict_attr_t const * attr_module_failure_message
Definition base.c:36
static fr_dict_attr_t const * attr_module_success_message
Definition base.c:37
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition base.c:745
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
Definition base.c:401
static int mod_load(void)
Definition base.c:228
static void mod_unload(void)
Definition base.c:237
process_radius_auth_t auth
Authentication configuration.
Definition base.c:149
CONF_SECTION * access_challenge
Definition base.c:111
static fr_dict_attr_t const * attr_user_password
Definition base.c:65
CONF_SECTION * coa_nak
Definition base.c:120
static xlat_arg_parser_t const xlat_func_radius_secret_verify_args[]
Definition base.c:822
CONF_SECTION * disconnect_ack
Definition base.c:123
CONF_SECTION * protocol_error
Definition base.c:127
CONF_SECTION * new_client
Definition base.c:129
static fr_dict_attr_t const * attr_stripped_user_name
Definition base.c:58
fr_dict_attr_autoload_t process_radius_dict_attr[]
Definition base.c:71
fr_value_box_list_head_t proxy_state
These need to be copied into the response in exactly the same order as they were added.
Definition base.c:155
static const conf_parser_t session_config[]
Definition base.c:169
CONF_SECTION * coa_request
Definition base.c:118
uint8_t state_server_id
Sets a specific byte in the state to allow the authenticating server to be identified in packet captu...
Definition base.c:138
fr_dict_enum_autoload_t process_radius_dict_enum[]
Definition base.c:96
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition base.c:892
fr_process_module_t process_radius
Definition base.c:1229
static fr_dict_attr_t const * attr_auth_type
Definition base.c:55
#define FR_RADIUS_PROCESS_CODE_VALID(_x)
Definition base.c:159
static void radius_request_pairs_to_reply(request_t *request, process_radius_request_pairs_t *rctx)
Definition base.c:265
CONF_SECTION * disconnect_nak
Definition base.c:124
CONF_SECTION * access_accept
Definition base.c:109
static fr_value_box_t const * enum_auth_type_reject
Definition base.c:93
static fr_dict_attr_t const * attr_error_cause
Definition base.c:67
CONF_SECTION * add_client
Definition base.c:130
static const conf_parser_t auth_config[]
Definition base.c:177
fr_time_delta_t session_timeout
Maximum time between the last response and next request.
Definition base.c:135
CONF_SECTION * server_cs
Our virtual server.
Definition base.c:146
CONF_SECTION * access_request
Definition base.c:108
static fr_dict_attr_t const * attr_proxy_state
Definition base.c:62
static process_radius_request_pairs_t * radius_request_pairs_store(request_t *request)
Keep a copy of some attributes to keep them from being tamptered with.
Definition base.c:236
static void radius_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *list, bool received)
Definition base.c:193
static fr_value_box_t const * enum_auth_type_accept
Definition base.c:92
uint32_t max_session
Maximum ongoing session allowed.
Definition base.c:136
CONF_SECTION * status_server
Definition base.c:116
CONF_SECTION * access_reject
Definition base.c:110
static fr_dict_attr_t const * attr_acct_status_type
Definition base.c:60
CONF_SECTION * disconnect_request
Definition base.c:122
CONF_SECTION * accounting_request
Definition base.c:113
CONF_SECTION * coa_ack
Definition base.c:119
CONF_SECTION * do_not_respond
Definition base.c:126
process_radius_sections_t sections
Pointers to various config sections we need to execute.
Definition base.c:147
static fr_dict_attr_t const * attr_original_packet_code
Definition base.c:66
static const conf_parser_t config[]
Definition base.c:183
fr_dict_autoload_t process_radius_dict[]
Definition base.c:49
fr_state_tree_t * state_tree
State tree to link multiple requests/responses.
Definition base.c:142
static fr_dict_attr_t const * attr_event_timestamp
Definition base.c:68
CONF_SECTION * accounting_response
Definition base.c:114
CONF_SECTION * deny_client
Definition base.c:131
Records fields from the original request so we have a known good copy.
Definition base.c:154
#define PROCESS_TRACE
Trace each state function as it's entered.
Definition process.h:65
module_t common
Common fields for all loadable modules.
Definition process.h:55
Common public symbol definition for all process modules.
Definition process.h:54
int fr_radius_verify(uint8_t *packet, uint8_t const *vector, uint8_t const *secret, size_t secret_len, bool require_message_authenticator, bool limit_proxy_state)
Verify a request / response packet.
Definition base.c:778
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Definition base.c:112
#define fr_assert(_expr)
Definition rad_assert.h:38
static char * secret
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG_ENABLED2()
Definition radclient.h:50
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define RDEBUG(fmt,...)
Definition radclient.h:53
#define RDEBUG_ENABLED()
Definition radclient.h:49
static void send_reply(int sockfd, fr_channel_data_t *reply)
#define FR_RADIUS_PACKET_CODE_VALID(_x)
Definition radius.h:52
void fr_rand_buffer(void *start, size_t length)
Definition rand.c:125
fr_table_num_sorted_t const rcode_table[]
Definition rcode.c:35
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:49
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:48
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
Definition rcode.h:50
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:44
#define request_is_dynamic_client(_x)
Definition request.h:162
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
void * data
Module's instance data.
Definition module.h:271
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:198
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition pair.h:129
fr_state_tree_t * fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, bool thread_safe, uint32_t max_sessions, fr_time_delta_t timeout, uint8_t server_id, uint32_t context_id)
Initialise a new state tree.
Definition state.c:222
void fr_state_discard(fr_state_tree_t *state, request_t *request)
Called when sending an Access-Accept/Access-Reject to discard state information.
Definition state.c:606
int fr_request_to_state(fr_state_tree_t *state, request_t *request)
Transfer ownership of the state fr_pair_ts and ctx, back to a state entry.
Definition state.c:737
int fr_state_to_request(fr_state_tree_t *state, request_t *request)
Copy a pointer to the head of the list of state fr_pair_ts (and their ctx) into the request.
Definition state.c:660
unlang_action_t unlang_module_yield_to_section(rlm_rcode_t *p_result, request_t *request, CONF_SECTION *subcs, rlm_rcode_t default_rcode, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Definition module.c:248
eap_aka_sim_process_conf_t * inst
#define RESUME(_x)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
#define talloc_get_type_abort_const
Definition talloc.h:282
static fr_unix_time_t fr_unix_time_sub_time_delta(fr_unix_time_t a, fr_time_delta_t b)
Definition time.h:341
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
Definition time.h:688
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
Definition xlat.h:381
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:168
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumend by an xlat function.
Definition xlat.h:147
unsigned int code
Packet code (type).
Definition packet.h:61
fr_socket_t socket
This packet was received on.
Definition packet.h:57
int id
Packet ID (used to link requests/responses).
Definition packet.h:60
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:78
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:676
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:3740
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:621
#define fr_box_ipaddr(_val)
Definition value.h:294
static fr_value_box_t * fr_value_box_acopy(TALLOC_CTX *ctx, fr_value_box_t const *src)
Copy an existing box, allocating a new box to hold its contents.
Definition value.h:711
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:206
static size_t char ** out
Definition value.h:997
int virtual_server_section_attribute_define(CONF_SECTION *server_cs, char const *subcs_name, fr_dict_attr_t const *da)
Define a values for Auth-Type attributes by the sections present in a virtual-server.
#define COMPILE_TERMINATOR
section_name_t const * section
Identifier for the section.
Processing sections which are allowed in this virtual server.
An xlat calling ctx.
Definition xlat_ctx.h:49
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
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition xlat_func.c:218
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:519