The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
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: 96c1be51e0376168b63c2f04fb7511210e6c4308 $
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/state.h>
33
34#include <freeradius-devel/unlang/module.h>
35#include <freeradius-devel/unlang/xlat_func.h>
36
37#include <freeradius-devel/util/debug.h>
38
40static fr_dict_t const *dict_radius;
41
44 { .out = &dict_freeradius, .proto = "freeradius" },
45 { .out = &dict_radius, .proto = "radius" },
47};
48
53
62
65 { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
66 { .out = &attr_module_failure_message, .name = "Module-Failure-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
67 { .out = &attr_module_success_message, .name = "Module-Success-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
68 { .out = &attr_stripped_user_name, .name = "Stripped-User-Name", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
69
70 { .out = &attr_acct_status_type, .name = "Acct-Status-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
71 { .out = &attr_proxy_state, .name = "Proxy-State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
72 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
73 { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
74 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
75 { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius },
76
77 { .out = &attr_original_packet_code, .name = "Extended-Attribute-1.Original-Packet-Code", .type = FR_TYPE_UINT32, .dict = &dict_radius },
78 { .out = &attr_error_cause, .name = "Error-Cause", .type = FR_TYPE_UINT32, .dict = &dict_radius },
79
81};
82
85
88 { .out = &enum_auth_type_accept, .name = "Accept", .attr = &attr_auth_type },
89 { .out = &enum_auth_type_reject, .name = "Reject", .attr = &attr_auth_type },
91};
92
93/*
94 * RADIUS state machine configuration
95 */
124
125typedef struct {
126 fr_state_config_t session; //!< track state session information.
127 fr_state_tree_t *state_tree; //!< State tree to link multiple requests/responses.
129
130typedef struct {
131 CONF_SECTION *server_cs; //!< Our virtual server.
132 process_radius_sections_t sections; //!< Pointers to various config sections
133 ///< we need to execute.
134 process_radius_auth_t auth; //!< Authentication configuration.
136
137/** Records fields from the original request so we have a known good copy
138 */
139typedef struct {
140 fr_value_box_list_head_t proxy_state; //!< These need to be copied into the response in exactly
141 ///< the same order as they were added.
144
145#define FR_RADIUS_PROCESS_CODE_VALID(_x) (FR_RADIUS_PACKET_CODE_VALID(_x) || (_x == FR_RADIUS_CODE_DO_NOT_RESPOND))
146
147#define PROCESS_PACKET_TYPE fr_radius_packet_code_t
148#define PROCESS_CODE_MAX FR_RADIUS_CODE_MAX
149#define PROCESS_CODE_DO_NOT_RESPOND FR_RADIUS_CODE_DO_NOT_RESPOND
150#define PROCESS_PACKET_CODE_VALID FR_RADIUS_PROCESS_CODE_VALID
151#define PROCESS_INST process_radius_t
152#define PROCESS_RCTX process_radius_rctx_t
153#define PROCESS_CODE_DYNAMIC_CLIENT FR_RADIUS_CODE_ACCESS_ACCEPT
154#include <freeradius-devel/server/process.h>
155
156static const conf_parser_t auth_config[] = {
157 { FR_CONF_POINTER("session", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) state_session_config },
158
160};
161
162static const conf_parser_t config[] = {
163 { FR_CONF_POINTER("Access-Request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) auth_config,
164 .offset = offsetof(process_radius_t, auth), },
165
167};
168
169/** Keep a copy of some attributes to keep them from being tampered with
170 *
171 */
172static inline CC_HINT(always_inline)
174{
175 fr_pair_t *proxy_state;
176
177 /*
178 * Don't bother allocing the struct if there's no proxy state to store
179 */
180 proxy_state = fr_pair_find_by_da(&request->request_pairs, NULL, attr_proxy_state);
181 if (!proxy_state) return;
182
183 fr_value_box_list_init(&rctx->proxy_state);
184
185 /*
186 * We don't use fr_pair_list_copy_by_da, to avoid doing the lookup for
187 * the first proxy-state attr again.
188 */
189 do {
190 fr_value_box_t *proxy_state_value;
191
192 MEM((proxy_state_value = fr_value_box_acopy(rctx, &proxy_state->data)));
193 fr_value_box_list_insert_tail(&rctx->proxy_state, proxy_state_value);
194 } while ((proxy_state = fr_pair_find_by_da(&request->request_pairs, proxy_state, attr_proxy_state)));
195}
196
197static inline CC_HINT(always_inline)
199{
200 /*
201 * Proxy-State is a link-level signal between RADIUS
202 * client and server. RFC 2865 Section 5.33 says that
203 * Proxy-State is an opaque field, and implementations
204 * most not examine it, interpret it, or assign it any
205 * meaning. Implementations must also copy all Proxy-State
206 * from the request to the reply.
207 *
208 * The rlm_radius module already deletes any Proxy-State
209 * from the reply before appending the proxy reply to the
210 * current reply.
211 *
212 * If any policy creates Proxy-State, that could affect
213 * individual RADIUS links (perhaps), and that would be
214 * wrong. As such, we nuke any nonsensical Proxy-State
215 * added by policies or errant modules, and instead just
216 * do exactly what the RFCs require us to do. No more.
217 */
218 fr_pair_delete_by_da(&request->reply_pairs, attr_proxy_state);
219
220 RDEBUG3("Adding Proxy-State attributes from request");
221 RINDENT();
222 fr_value_box_list_foreach(&rctx->proxy_state, proxy_state_value) {
223 fr_pair_t *vp;
224
225 MEM(vp = fr_pair_afrom_da(request->reply_ctx, attr_proxy_state));
226 if (unlikely(fr_value_box_copy(vp, &vp->data, proxy_state_value) < 0)) {
227 RDEBUG2("Failed to copy Proxy-State value %pV", proxy_state_value);
229 break;
230 }
231 fr_pair_append(&request->reply_pairs, vp);
232 RDEBUG3("reply.%pP", vp);
233 }
234 REXDENT();
235}
236
237/** A wrapper around recv generic which stores fields from the request
238 */
239RECV(generic_radius_request)
240{
241 radius_request_pairs_store(request, mctx->rctx);
242
243 return CALL_RECV(generic);
244}
245
246/** A wrapper around send generic which restores fields
247 *
248 */
249RESUME(generic_radius_response)
250{
251 radius_request_pairs_to_reply(request, talloc_get_type_abort(mctx->rctx, process_radius_rctx_t));
252
253 return CALL_RESUME(send_generic);
254}
255
256RECV(access_request)
257{
259
260 if (fr_state_restore(inst->auth.state_tree, request) < 0) {
261 return CALL_SEND_TYPE(FR_RADIUS_CODE_ACCESS_REJECT);
262 }
263
264 return CALL_RECV(generic_radius_request);
265}
266
267RESUME(auth_type);
268
269RESUME(access_request)
270{
271 rlm_rcode_t rcode = RESULT_RCODE;
272 fr_pair_t *vp;
273 CONF_SECTION *cs;
274 fr_dict_enum_value_t const *dv;
275 fr_process_state_t const *state;
277
279
281
282 /*
283 * See if the return code from "recv Access-Request" says we reject, or continue.
284 */
285 UPDATE_STATE(packet);
286
287 /*
288 * A policy or a module can hard-code the reply, in which case we can process that immediately,
289 * and bypass the "authenticate" section.
290 */
291 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_packet_type);
292 if (vp && FR_RADIUS_PROCESS_CODE_VALID(vp->vp_uint32)) {
293 request->reply->code = vp->vp_uint32;
294 (void) fr_pair_delete(&request->reply_pairs, vp);
295 } else {
296 /*
297 * Get the default reply packet based on the rcode.
298 */
299 request->reply->code = state->packet_type[rcode];
300 if (!request->reply->code) request->reply->code = state->default_reply;
301 }
302
303 /*
304 * Either the code above or a module set reject, we're done.
305 */
306 if (request->reply->code == FR_RADIUS_CODE_ACCESS_REJECT) {
307 RDEBUG("The 'recv Access-Request' section returned %s - rejecting the request",
308 fr_table_str_by_value(rcode_table, rcode, "<INVALID>"));
309
311 UPDATE_STATE(reply);
312
313 fr_assert(state->send != NULL);
314 return CALL_SEND_STATE(state);
315 }
316
317 /*
318 * Something set a reply, bypass the "authenticate" section.
319 */
320 if (request->reply->code) {
321 goto send_reply;
322 }
323
324 /*
325 * Run authenticate foo { ... }
326 *
327 * If we can't find Auth-Type, OR if we can't find
328 * Auth-Type = foo, then it's a reject.
329 */
330 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_auth_type);
331 if (!vp) {
332 RDEBUG("No 'Auth-Type' attribute found, cannot authenticate the user - rejecting the request");
333
334 reject:
335 request->reply->code = FR_RADIUS_CODE_ACCESS_REJECT;
336 goto send_reply;
337 }
338
339 dv = fr_dict_enum_by_value(vp->da, &vp->data);
340 if (!dv) {
341 RDEBUG("Invalid value for 'Auth-Type' attribute, cannot authenticate the user - rejecting the request");
342 goto reject;
343 }
344
345 /*
346 * The magic Auth-Type Accept value which means skip the authenticate section.
347 *
348 * And Reject means always reject. Tho the admin should instead just return "reject" from the
349 * section.
350 */
352 request->reply->code = FR_RADIUS_CODE_ACCESS_ACCEPT;
353 goto send_reply;
354
355 } else if (fr_value_box_cmp(enum_auth_type_reject, dv->value) == 0) {
356 goto reject;
357 }
358
359 cs = cf_section_find(inst->server_cs, "authenticate", dv->name);
360 if (!cs) {
361 RDEBUG2("No 'authenticate %s { ... }' section found - rejecting the request", dv->name);
362 goto reject;
363 }
364
365 /*
366 * Run the "Authenticate = foo" section.
367 *
368 * And continue with sending the generic reply.
369 */
370 return unlang_module_yield_to_section(RESULT_P, request,
371 cs, RLM_MODULE_NOOP, resume_auth_type,
372 NULL, 0, mctx->rctx);
373}
374
375RESUME(auth_type)
376{
377 static const fr_process_rcode_t auth_type_rcode = {
381 [RLM_MODULE_HANDLED] = 0,
388 };
389
390 rlm_rcode_t rcode = RESULT_RCODE;
391 fr_pair_t *vp;
392 fr_process_state_t const *state;
393
395
397
398 /*
399 * Allow user to specify response packet type here, too.
400 */
401 if (!auth_type_rcode[rcode]) {
402 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_packet_type);
403 if (vp && FR_RADIUS_PROCESS_CODE_VALID(vp->vp_uint32)) {
404 request->reply->code = vp->vp_uint32;
405 (void) fr_pair_delete(&request->reply_pairs, vp);
406 }
407 } else {
408 request->reply->code = auth_type_rcode[rcode];
409 }
410
411 switch (request->reply->code) {
412 case 0:
413 RDEBUG("No reply code was set. Forcing to Access-Reject");
414 request->reply->code = FR_RADIUS_CODE_ACCESS_REJECT;
416
417 /*
418 * Print complaints before running "send Access-Reject"
419 */
421 RDEBUG2("Failed to authenticate the user");
422
423 /*
424 * Maybe the shared secret is wrong?
425 */
426 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_password);
427 if (vp) {
428 if (RDEBUG_ENABLED2) {
429 uint8_t const *p;
430
431 p = (uint8_t const *) vp->vp_strvalue;
432 while (*p) {
433 int size;
434
435 size = fr_utf8_char(p, -1);
436 if (!size) {
437 RWDEBUG("Unprintable characters in the password. "
438 "Double-check the shared secret on the server "
439 "and the NAS!");
440 RWDEBUG("For more information, please see " DOC_ROOT_URL "/troubleshooting/network/shared_secret.html");
441 break;
442 }
443 p += size;
444 }
445 }
446 }
447 break;
448
449 /*
450 * Access-Challenge sections require a State. If there is
451 * none, create one here. This is so that the State
452 * attribute is accessible in the "send Access-Challenge"
453 * section.
454 */
456 if ((vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_state)) == NULL) {
457 uint8_t buffer[16];
458
459 fr_rand_buffer(buffer, sizeof(buffer));
460
462 fr_pair_value_memdup(vp, buffer, sizeof(buffer), false);
463 }
464 break;
465
466 default:
467 break;
468 }
469 UPDATE_STATE(reply);
470
471 fr_assert(state->send != NULL);
472 return state->send(p_result, mctx, request);
473}
474
475RESUME_FLAG(access_accept,UNUSED,)
476{
477 fr_pair_t *vp;
479
481
482 /*
483 * Check that there is a name which can be used to
484 * identify the user. The configuration depends on
485 * User-Name or Stripped-User-Name existing, and being
486 * (mostly) unique to that user.
487 */
488 if (!request->parent &&
489 ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_name)) != NULL) &&
490 (vp->vp_strvalue[0] == '@') &&
491 !fr_pair_find_by_da(&request->request_pairs, NULL, attr_stripped_user_name)) {
492 RWDEBUG("User-Name is anonymized, and no Stripped-User-Name exists.");
493 RWDEBUG("It may be difficult or impossible to identify the user.");
494 RWDEBUG("Please update Stripped-User-Name with information which identifies the user.");
495 }
496
497 fr_state_discard(inst->auth.state_tree, request);
498 radius_request_pairs_to_reply(request, mctx->rctx);
500}
501
502RESUME_FLAG(access_reject,UNUSED,)
503{
505
507
508 fr_state_discard(inst->auth.state_tree, request);
509 radius_request_pairs_to_reply(request, mctx->rctx);
511}
512
513RESUME(access_challenge)
514{
516
518
519 /*
520 * Cache the state context, unless this is a subrequest.
521 * Subrequest state context will be handled by the caller.
522 *
523 * If this fails, don't respond to the request.
524 */
525 if (!request->parent && fr_state_store(inst->auth.state_tree, request) < 0) {
526 return CALL_SEND_TYPE(FR_RADIUS_CODE_DO_NOT_RESPOND);
527 }
528
529 fr_assert(request->reply->code == FR_RADIUS_CODE_ACCESS_CHALLENGE);
530 radius_request_pairs_to_reply(request, mctx->rctx);
532}
533
534/** A wrapper around recv generic which stores fields from the request
535 */
536RECV(accounting_request)
537{
538 radius_request_pairs_store(request, mctx->rctx);
539
540 return CALL_RECV(generic);
541}
542
543RESUME(acct_type)
544{
545 static const fr_process_rcode_t acct_type_rcode = {
552 };
553
554 rlm_rcode_t rcode = RESULT_RCODE;
555 fr_process_state_t const *state;
556
558
560 fr_assert(FR_RADIUS_PROCESS_CODE_VALID(request->reply->code));
561
562 if (acct_type_rcode[rcode]) {
563 fr_assert(acct_type_rcode[rcode] == FR_RADIUS_CODE_DO_NOT_RESPOND);
564
565 request->reply->code = acct_type_rcode[rcode];
566 UPDATE_STATE(reply);
567
568 RDEBUG("The 'accounting' section returned %s - not sending a response",
569 fr_table_str_by_value(rcode_table, rcode, "<INVALID>"));
570
571 fr_assert(state->send != NULL);
572 return state->send(p_result, mctx, request);
573 }
574
575 request->reply->code = FR_RADIUS_CODE_ACCOUNTING_RESPONSE;
576 UPDATE_STATE(reply);
577
578 fr_assert(state->send != NULL);
579 return state->send(p_result, mctx, request);
580}
581
582RESUME(accounting_request)
583{
584 rlm_rcode_t rcode = RESULT_RCODE;
585 fr_pair_t *vp;
586 CONF_SECTION *cs;
587 fr_dict_enum_value_t const *dv;
588 fr_process_state_t const *state;
590
592
594
595 UPDATE_STATE(packet);
596 fr_assert(state->packet_type[rcode] != 0);
597
598 request->reply->code = state->packet_type[rcode];
599 UPDATE_STATE_CS(reply);
600
601 if (request->reply->code == FR_RADIUS_CODE_DO_NOT_RESPOND) {
602 RDEBUG("The 'recv Accounting-Request' section returned %s - not sending a response",
603 fr_table_str_by_value(rcode_table, rcode, "<INVALID>"));
604
606 fr_assert(state->send != NULL);
607 return CALL_SEND_STATE(state);
608 }
609
610 /*
611 * Run accounting foo { ... }
612 */
613 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_status_type);
614 if (!vp) goto send_reply;
615
616 dv = fr_dict_enum_by_value(vp->da, &vp->data);
617 if (!dv) goto send_reply;
618
619 cs = cf_section_find(inst->server_cs, "accounting", dv->name);
620 if (!cs) {
621 RDEBUG2("No 'accounting %s { ... }' section found - skipping...", dv->name);
622 goto send_reply;
623 }
624
625 /*
626 * Run the "Acct-Status-Type = foo" section.
627 *
628 * And continue with sending the generic reply.
629 */
630 return unlang_module_yield_to_section(RESULT_P, request,
631 cs, RLM_MODULE_NOOP, resume_acct_type,
632 NULL, 0, mctx->rctx);
633}
634
635#if 0
636// @todo - send canned responses like in v3?
637RECV(status_server)
638{
640}
641
642RESUME(status_server)
643{
645}
646#endif
647
648RESUME_FLAG(protocol_error,UNUSED,)
649{
650 fr_pair_t *vp;
652
654
655 fr_assert(FR_RADIUS_PACKET_CODE_VALID(request->reply->code));
656
657 /*
658 * https://tools.ietf.org/html/rfc7930#section-4
659 */
660 vp = fr_pair_find_by_da_nested(&request->reply_pairs, NULL, attr_original_packet_code);
661 if (!vp) {
662 vp = fr_pair_afrom_da(request->reply_ctx, attr_original_packet_code);
663 if (vp) {
664 vp->vp_uint32 = request->packet->code;
665 fr_pair_append(&request->reply_pairs, vp);
666 }
667 }
668
669 /*
670 * If there's no Error-Cause, then include a generic 404.
671 */
672 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_error_cause);
673 if (!vp) {
674 vp = fr_pair_afrom_da(request->reply_ctx, attr_error_cause);
675 if (vp) {
676 vp->vp_uint32 = FR_ERROR_CAUSE_VALUE_INVALID_REQUEST;
677 fr_pair_append(&request->reply_pairs, vp);
678 }
679 }
680
681 /*
682 * Discard any session state associated with the request.
683 */
684 if (request->packet->code == FR_RADIUS_CODE_ACCESS_REQUEST) {
685 fr_state_discard(inst->auth.state_tree, request);
686 }
687
688 /*
689 * Add Proxy-State back.
690 */
691 radius_request_pairs_to_reply(request, talloc_get_type_abort(mctx->rctx, process_radius_rctx_t));
692
693 /*
694 * And do the generic processing after running a "send" section.
695 */
696 return CALL_RESUME(send_generic);
697}
698
699static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
700{
701 fr_process_state_t const *state;
702
704
706
707 request->component = "radius";
708 request->module = NULL;
709 fr_assert(request->proto_dict == dict_radius);
710
711 fr_assert(FR_RADIUS_PACKET_CODE_VALID(request->packet->code));
712
713 UPDATE_STATE(packet);
714
715 if (!state->recv) {
716 REDEBUG("Invalid packet type (%u)", request->packet->code);
718 }
719
720 if (unlikely(request_is_dynamic_client(request))) {
721 return new_client(p_result, mctx, request);
722 }
723
724 return state->recv(p_result, mctx, request);
725}
726
728 { .required = true, .single = true, .type = FR_TYPE_OCTETS },
730};
731
732/** Validates a request against a known shared secret
733 *
734 * Designed for the specific purpose of verifying dynamic clients
735 * against a known shared secret in a `new client` section.
736 *
737 * Example:
738@verbatim
739%radius.secret.verify(<secret>)
740@endverbatim
741 *
742 * @ingroup xlat_functions
743 */
745 request_t *request, fr_value_box_list_t *args)
746{
748 int ret;
749 bool require_message_authenticator = false;
750
752
753 if (request->proto_dict != dict_radius) return XLAT_ACTION_FAIL;
754
755 MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL));
756
757 /*
758 * Only Access-Requests require a Message-Authenticator.
759 * All the other packet types are signed using the
760 * authenticator field.
761 */
762 if (request->packet->code == FR_RADIUS_CODE_ACCESS_REQUEST) require_message_authenticator = true;
763
764 ret = fr_radius_verify(request->packet->data, NULL, secret->vb_octets, secret->vb_length, require_message_authenticator, false);
765 switch (ret) {
766 case 0:
767 vb->vb_bool = true;
768 break;
769
770 default:
771 RPEDEBUG("Invalid packet");
772 return XLAT_ACTION_FAIL;
773
776 RPEDEBUG("Failed to verify the packet signature");
777 vb->vb_bool = false;
778 break;
779 }
781
782 return XLAT_ACTION_DONE;
783}
784
785static int mod_instantiate(module_inst_ctx_t const *mctx)
786{
787 process_radius_t *inst = talloc_get_type_abort(mctx->mi->data, process_radius_t);
788
789 inst->server_cs = cf_item_to_section(cf_parent(mctx->mi->conf));
790
791 FR_INTEGER_BOUND_CHECK("session.max_rounds", inst->auth.session.max_rounds, >=, 32);
792 FR_INTEGER_BOUND_CHECK("session.max_rounds", inst->auth.session.max_rounds, <=, 100);
793
794 inst->auth.session.thread_safe = main_config->spawn_workers;
795 inst->auth.session.context_id = fr_hash_string(cf_section_name2(inst->server_cs));
796
797 MEM(inst->auth.state_tree = fr_state_tree_init(inst, attr_state, &inst->auth.session));
798
799 return 0;
800}
801
802static int mod_bootstrap(module_inst_ctx_t const *mctx)
803{
804 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(mctx->mi->conf));
805
806 if (virtual_server_section_attribute_define(server_cs, "authenticate", attr_auth_type) < 0) return -1;
807
808 return 0;
809}
810
811static int mod_load(void)
812{
813 xlat_t *xlat;
814
815 if (unlikely(!(xlat = xlat_func_register(NULL, "radius.secret.verify", xlat_func_radius_secret_verify,
816 FR_TYPE_BOOL)))) return -1;
817
819
820 return 0;
821}
822
823static void mod_unload(void)
824{
825 xlat_func_unregister("radius.secret.verify");
826}
827
828/*
829 * rcodes not listed under a packet_type
830 * mean that the packet code will not be
831 * changed.
832 */
833static fr_process_state_t const process_state[] = {
835 .packet_type = {
842 },
843 .default_rcode = RLM_MODULE_NOOP,
844 .recv = recv_access_request,
845 .resume = resume_access_request,
846 .section_offset = offsetof(process_radius_sections_t, access_request),
847 },
849 .packet_type = {
855 },
856 .default_rcode = RLM_MODULE_NOOP,
857 .result_rcode = RLM_MODULE_OK,
858 .send = send_generic,
859 .resume = resume_access_accept,
860 .section_offset = offsetof(process_radius_sections_t, access_accept),
861 },
863 .packet_type = {
869 },
870 .default_rcode = RLM_MODULE_NOOP,
871 .result_rcode = RLM_MODULE_REJECT,
872 .send = send_generic,
873 .resume = resume_access_reject,
874 .section_offset = offsetof(process_radius_sections_t, access_reject),
875 },
877 .packet_type = {
883 },
884 .default_rcode = RLM_MODULE_NOOP,
885 .result_rcode = RLM_MODULE_OK,
886 .send = send_generic,
887 .resume = resume_access_challenge,
888 .section_offset = offsetof(process_radius_sections_t, access_challenge),
889 },
890
892 .packet_type = {
897
904 },
905 .default_rcode = RLM_MODULE_NOOP,
906 .recv = recv_accounting_request,
907 .resume = resume_accounting_request,
908 .section_offset = offsetof(process_radius_sections_t, accounting_request),
909 },
911 .packet_type = {
918 },
919 .default_rcode = RLM_MODULE_NOOP,
920 .result_rcode = RLM_MODULE_OK,
921 .send = send_generic,
922 .resume = resume_generic_radius_response,
923 .section_offset = offsetof(process_radius_sections_t, accounting_response),
924 },
925 [ FR_RADIUS_CODE_STATUS_SERVER ] = { /* @todo - negotiation, stats, etc. */
926 .packet_type = {
929
937 },
938 .default_rcode = RLM_MODULE_NOOP,
939 .recv = recv_generic,
940 .resume = resume_recv_generic,
941 .section_offset = offsetof(process_radius_sections_t, status_server),
942 },
944 .packet_type = {
949
955 },
956 .default_rcode = RLM_MODULE_NOOP,
957 .recv = recv_generic_radius_request,
958 .resume = resume_recv_generic,
959 .section_offset = offsetof(process_radius_sections_t, coa_request),
960 },
962 .packet_type = {
968 },
969 .default_rcode = RLM_MODULE_NOOP,
970 .result_rcode = RLM_MODULE_OK,
971 .send = send_generic,
972 .resume = resume_generic_radius_response,
973 .section_offset = offsetof(process_radius_sections_t, coa_ack),
974 },
976 .packet_type = {
982 },
983 .default_rcode = RLM_MODULE_NOOP,
984 .result_rcode = RLM_MODULE_NOTFOUND,
985 .send = send_generic,
986 .resume = resume_generic_radius_response,
987 .section_offset = offsetof(process_radius_sections_t, coa_nak),
988 },
990 .packet_type = {
995
1001 },
1002 .default_rcode = RLM_MODULE_NOOP,
1003 .recv = recv_generic_radius_request,
1004 .resume = resume_recv_generic,
1005 .section_offset = offsetof(process_radius_sections_t, disconnect_request),
1006 },
1008 .packet_type = {
1014 },
1015 .default_rcode = RLM_MODULE_NOOP,
1016 .result_rcode = RLM_MODULE_OK,
1017 .send = send_generic,
1018 .resume = resume_generic_radius_response,
1019 .section_offset = offsetof(process_radius_sections_t, disconnect_ack),
1020 },
1022 .packet_type = {
1028 },
1029 .default_rcode = RLM_MODULE_NOOP,
1030 .result_rcode = RLM_MODULE_NOTFOUND,
1031 .send = send_generic,
1032 .resume = resume_generic_radius_response,
1033 .section_offset = offsetof(process_radius_sections_t, disconnect_nak),
1034 },
1035 [ FR_RADIUS_CODE_PROTOCOL_ERROR ] = { /* @todo - fill out required fields */
1036 .packet_type = {
1042 },
1043 .default_rcode = RLM_MODULE_NOOP,
1044 .result_rcode = RLM_MODULE_OK,
1045 .send = send_generic,
1046 .resume = resume_protocol_error,
1047 .section_offset = offsetof(process_radius_sections_t, protocol_error),
1048 },
1050 .packet_type = {
1055
1062 },
1063 .default_rcode = RLM_MODULE_NOOP,
1064 .result_rcode = RLM_MODULE_HANDLED,
1065 .send = send_generic,
1066 .resume = resume_send_generic,
1067 .section_offset = offsetof(process_radius_sections_t, do_not_respond),
1068 }
1069};
1070
1072 {
1073 .section = SECTION_NAME("recv", "Access-Request"),
1074 .actions = &mod_actions_authorize,
1075 .offset = PROCESS_CONF_OFFSET(access_request),
1076 },
1077 {
1078 .section = SECTION_NAME("send", "Access-Accept"),
1080 .offset = PROCESS_CONF_OFFSET(access_accept),
1081 },
1082 {
1083 .section = SECTION_NAME("send", "Access-Challenge"),
1085 .offset = PROCESS_CONF_OFFSET(access_challenge),
1086 },
1087 {
1088 .section = SECTION_NAME("send", "Access-Reject"),
1090 .offset = PROCESS_CONF_OFFSET(access_reject),
1091 },
1092
1093 {
1094 .section = SECTION_NAME("recv", "Accounting-Request"),
1096 .offset = PROCESS_CONF_OFFSET(accounting_request),
1097 },
1098 {
1099 .section = SECTION_NAME("send", "Accounting-Response"),
1101 .offset = PROCESS_CONF_OFFSET(accounting_response),
1102 },
1103
1104 {
1105 .section = SECTION_NAME("recv", "Status-Server"),
1107 .offset = PROCESS_CONF_OFFSET(status_server),
1108 },
1109 {
1110 .section = SECTION_NAME("recv", "CoA-Request"),
1112 .offset = PROCESS_CONF_OFFSET(coa_request),
1113 },
1114 {
1115 .section = SECTION_NAME("send", "CoA-ACK"),
1117 .offset = PROCESS_CONF_OFFSET(coa_ack),
1118 },
1119 {
1120 .section = SECTION_NAME("send", "CoA-NAK"),
1122 .offset = PROCESS_CONF_OFFSET(coa_nak),
1123 },
1124 {
1125 .section = SECTION_NAME("recv", "Disconnect-Request"),
1127 .offset = PROCESS_CONF_OFFSET(disconnect_request),
1128 },
1129 {
1130 .section = SECTION_NAME("send", "Disconnect-ACK"),
1132 .offset = PROCESS_CONF_OFFSET(disconnect_ack),
1133 },
1134 {
1135 .section = SECTION_NAME("send", "Disconnect-NAK"),
1137 .offset = PROCESS_CONF_OFFSET(disconnect_nak),
1138 },
1139 {
1140 .section = SECTION_NAME("send", "Protocol-Error"),
1142 .offset = PROCESS_CONF_OFFSET(protocol_error),
1143 },
1144 {
1145 .section = SECTION_NAME("send", "Do-Not-Respond"),
1147 .offset = PROCESS_CONF_OFFSET(do_not_respond),
1148 },
1149 {
1150 .section = SECTION_NAME("authenticate", CF_IDENT_ANY),
1152 },
1153 {
1154 .section = SECTION_NAME("accounting", CF_IDENT_ANY),
1156 },
1157
1158 DYNAMIC_CLIENT_SECTIONS,
1159
1161};
1162
1165 .common = {
1166 .magic = MODULE_MAGIC_INIT,
1167 .name = "radius",
1168 .config = config,
1171
1172 .onload = mod_load,
1173 .unload = mod_unload,
1174 .bootstrap = mod_bootstrap,
1175 .instantiate = mod_instantiate
1176 },
1177 .process = mod_process,
1178 .compile_list = compile_list,
1179 .dict = &dict_radius,
1180 .packet_type = &attr_packet_type
1181};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
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:343
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:669
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:529
#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:334
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:423
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:606
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1359
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:1201
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:692
#define cf_parent(_cf)
Definition cf_util.h:118
#define CF_IDENT_ANY
Definition cf_util.h:80
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 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_value_box_t const ** out
Enumeration value.
Definition dict.h:281
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:292
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:305
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:257
fr_dict_enum_value_t const * 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:3632
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:311
char const * name
Enum name.
Definition dict.h:254
Specifies an attribute which must be present for the module to function.
Definition dict.h:291
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:304
Specifies a value which must be present for the module to function.
Definition dict.h:280
Value of an enumerated attribute.
Definition dict.h:253
#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 known shared secret.
Definition base.c:744
uint32_t fr_hash_string(char const *p)
Definition hash.c:900
talloc_free(hp)
static fr_dict_t const * dict_freeradius
Definition base.c:37
fr_dict_attr_t const * attr_packet_type
Definition base.c:91
fr_dict_t const * dict_radius
Definition base.c:76
fr_dict_attr_t const * attr_user_name
Definition base.c:101
static fr_dict_attr_t const * attr_module_failure_message
Definition log.c:206
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:460
#define RWDEBUG(fmt,...)
Definition log.h:378
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RPEDEBUG(fmt,...)
Definition log.h:393
#define RINDENT()
Indent R* messages by one level.
Definition log.h:447
main_config_t const * main_config
Main server configuration.
Definition main_config.c:56
bool spawn_workers
Should the server spawn threads.
Definition main_config.h:58
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
unsigned char uint8_t
unlang_mod_actions_t const mod_actions_preacct
Definition mod_action.c:61
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:77
unlang_mod_actions_t const mod_actions_authorize
Definition mod_action.c:45
unlang_mod_actions_t const mod_actions_postauth
Definition mod_action.c:92
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Definition mod_action.h:69
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
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:2962
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:784
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
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:1352
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:1696
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:290
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
Definition pair.c:1833
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(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition base.c:168
static const virtual_server_compile_t compile_list[]
Definition base.c:192
static fr_process_state_t const process_state[]
Definition base.c:68
RESUME_FLAG(recv_bfd, UNUSED,)
Definition base.c:76
static fr_dict_attr_t const * attr_module_success_message
Definition base.c:36
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
Definition base.c:348
static int mod_load(void)
Definition base.c:228
static void mod_unload(void)
Definition base.c:237
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition base.c:213
process_radius_auth_t auth
Authentication configuration.
Definition base.c:134
CONF_SECTION * access_challenge
Definition base.c:102
static fr_dict_attr_t const * attr_user_password
Definition base.c:59
CONF_SECTION * coa_nak
Definition base.c:111
static fr_dict_attr_t const * attr_state
Definition base.c:57
static xlat_arg_parser_t const xlat_func_radius_secret_verify_args[]
Definition base.c:727
CONF_SECTION * disconnect_ack
Definition base.c:114
CONF_SECTION * protocol_error
Definition base.c:118
CONF_SECTION * new_client
Definition base.c:120
static fr_dict_attr_t const * attr_stripped_user_name
Definition base.c:52
fr_dict_attr_autoload_t process_radius_dict_attr[]
Definition base.c:64
CONF_SECTION * coa_request
Definition base.c:109
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:140
fr_dict_enum_autoload_t process_radius_dict_enum[]
Definition base.c:87
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition base.c:802
fr_process_module_t process_radius
Definition base.c:1164
static fr_dict_attr_t const * attr_auth_type
Definition base.c:49
static void radius_request_pairs_to_reply(request_t *request, process_radius_rctx_t *rctx)
Definition base.c:198
#define FR_RADIUS_PROCESS_CODE_VALID(_x)
Definition base.c:145
CONF_SECTION * disconnect_nak
Definition base.c:115
CONF_SECTION * access_accept
Definition base.c:100
static fr_value_box_t const * enum_auth_type_reject
Definition base.c:84
static void radius_request_pairs_store(request_t *request, process_radius_rctx_t *rctx)
Keep a copy of some attributes to keep them from being tampered with.
Definition base.c:173
static fr_dict_attr_t const * attr_error_cause
Definition base.c:61
CONF_SECTION * add_client
Definition base.c:121
static const conf_parser_t auth_config[]
Definition base.c:156
CONF_SECTION * server_cs
Our virtual server.
Definition base.c:131
CONF_SECTION * access_request
Definition base.c:99
static fr_dict_attr_t const * attr_proxy_state
Definition base.c:56
static fr_value_box_t const * enum_auth_type_accept
Definition base.c:83
CONF_SECTION * status_server
Definition base.c:107
CONF_SECTION * access_reject
Definition base.c:101
static fr_dict_attr_t const * attr_acct_status_type
Definition base.c:54
CONF_SECTION * disconnect_request
Definition base.c:113
CONF_SECTION * accounting_request
Definition base.c:104
CONF_SECTION * coa_ack
Definition base.c:110
CONF_SECTION * do_not_respond
Definition base.c:117
fr_state_config_t session
track state session information.
Definition base.c:126
process_radius_sections_t sections
Pointers to various config sections we need to execute.
Definition base.c:132
static fr_dict_attr_t const * attr_original_packet_code
Definition base.c:60
unlang_result_t result
Definition base.c:142
static const conf_parser_t config[]
Definition base.c:162
fr_dict_autoload_t process_radius_dict[]
Definition base.c:43
fr_state_tree_t * state_tree
State tree to link multiple requests/responses.
Definition base.c:127
CONF_SECTION * accounting_response
Definition base.c:105
CONF_SECTION * deny_client
Definition base.c:122
Records fields from the original request so we have a known good copy.
Definition base.c:139
#define PROCESS_TRACE
Trace each state function as it's entered.
Definition process.h:55
#define PROCESS_CONF_OFFSET(_x)
Definition process.h:79
module_t common
Common fields for all loadable modules.
Common public symbol definition for all process modules.
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 the signature of a request / response packet.
Definition base.c:834
#define fr_assert(_expr)
Definition rad_assert.h:37
static char * secret
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED2()
#define RDEBUG2(fmt,...)
#define RDEBUG(fmt,...)
static void send_reply(int sockfd, fr_channel_data_t *reply)
@ FR_RADIUS_FAIL_VERIFY
Definition radius.h:113
@ FR_RADIUS_FAIL_MA_INVALID
Definition radius.h:109
#define FR_RADIUS_PACKET_CODE_VALID(_x)
Definition radius.h:51
void fr_rand_buffer(void *start, size_t length)
Definition rand.c:124
fr_table_num_sorted_t const rcode_table[]
Definition rcode.c:35
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:51
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:49
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition rcode.h:52
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:47
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
Definition rcode.h:56
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:53
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:55
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:54
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
Definition rcode.h:57
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:50
#define request_is_dynamic_client(_x)
Definition request.h:189
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:39
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:351
void * data
Module's instance data.
Definition module.h:293
#define MODULE_RCTX(_ctype)
Definition module.h:259
#define MODULE_INST(_ctype)
Definition module.h:257
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:206
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition pair.h:129
int fr_state_restore(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:764
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:685
int fr_state_store(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:840
const conf_parser_t state_session_config[]
Definition state.c:59
fr_state_tree_t * fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, fr_state_config_t const *config)
Initialise a new state tree.
Definition state.c:232
unlang_action_t unlang_module_yield_to_section(unlang_result_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:236
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:804
#define talloc_get_type_abort_const
Definition talloc.h:117
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
Definition xlat.h:383
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
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 consumed by an xlat function.
Definition xlat.h:145
#define DOC_ROOT_URL
Definition version.h:87
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:748
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:4394
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:644
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:744
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:224
static size_t char ** out
Definition value.h:1030
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.
section_name_t const * section
Identifier for the section.
#define COMPILE_TERMINATOR
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:216
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:509