25RCSID(
"$Id: 26120db98034064bdc1926c0e3cf9c4b82f4c585 $")
27#include <freeradius-devel/io/application.h>
28#include <freeradius-devel/server/modpriv.h>
29#include <freeradius-devel/unlang/xlat_func.h>
30#include <freeradius-devel/util/debug.h>
31#include <freeradius-devel/util/dlist.h>
313 cf_log_err(ci,
"Unknown or invalid RADIUS packet type '%s'", type_str);
317 code = type_enum->
value->vb_uint32;
323 cf_log_err(ci,
"Invalid setting of 'type = Status-Server'. Status-Server packets cannot be proxied.");
368 cf_log_err(ci,
"Unknown or invalid RADIUS packet type '%s'", type_str);
372 code = type_enum->
value->vb_uint32;
388 memcpy(
out, &code,
sizeof(code));
409 if (!map->
rhs)
return 0;
414 cf_log_err(map->
ci,
"Cannot assign dynamic values here");
426 if (da->flags.internal) {
469 map_list_t *
head = (map_list_t *)
out;
476 if (name2 && (strcmp(name2,
"request") != 0)) {
477 cf_log_err(cs,
"Only 'request' can be specified as the destination list");
496 if (rcode < 0)
return -1;
497 if (map_list_empty(
head)) {
498 cf_log_err(cs,
"Invalid configuration - status check packets cannot be empty");
519 RWDEBUG(
"Status-Server is reserved for internal use, and cannot be sent manually.");
523 if (!
inst->allowed[request->packet->code]) {
524 REDEBUG(
"Packet code %s is disallowed by the configuration",
535 unsigned int count = 0;
541 if (
vp->vp_length !=
sizeof(
inst->common_ctx.proxy_state))
continue;
543 if (memcmp(
vp->vp_octets, &
inst->common_ctx.proxy_state,
544 sizeof(
inst->common_ctx.proxy_state)) == 0) {
552 RWARN(
"Canceling proxy due to loop of multiple %pV",
vp);
556 RWARN(
"Proxied packet contains our own %pV",
vp);
557 RWARN(
"Check if there is a proxy loop. Perhaps the server has been configured to proxy to itself.");
587 if (!request->packet->code) {
588 REDEBUG(
"You MUST specify a packet code");
594 REDEBUG(
"Invalid packet code %u", request->packet->code);
604 REDEBUG(
"When using 'mode = unconnected-*', this module cannot be used in-place. Instead, it must be called via a function call");
610 REDEBUG(
"Cannot proxy packets which define dynamic clients");
636 inst->received_message_authenticator = talloc_zero(NULL,
bool);
642 if (
inst->fd_config.filename && (
inst->fd_config.flags != O_WRONLY)) {
643 cf_log_info(
conf,
"Setting 'flags = write-only' for writing to a file");
645 inst->fd_config.flags = O_WRONLY | O_APPEND;
647 }
else if (
inst->fd_config.filename) {
648 cf_log_err(
conf,
"When using an output 'filename', you MUST set 'mode = replicate'");
655 inst->fd_config.flags = O_RDWR;
672 switch (
inst->mode) {
677 if (
inst->fd_config.filename) {
678 cf_log_err(
conf,
"Cannot set 'filename' here - it is only supported for 'mode=replicate'");
686 if (
inst->fd_config.src_port) {
687 cf_log_err(
conf,
"Cannot 'src_port' here - it can only be set for replicating packets");
707 if (!
inst->fd_config.src_port_start && !
inst->fd_config.src_port_end)
break;
709 if (
inst->fd_config.path) {
710 cf_log_err(
conf,
"Cannot set 'src_port_start' or 'src_port_end' for outgoing Unix sockets");
717 if (
inst->fd_config.src_port_start) {
718 if (!
inst->fd_config.src_port_end) {
719 cf_log_err(
conf,
"Range has 'src_port_start', but is missing 'src_port_end'");
723 if (
inst->fd_config.src_port_start >=
inst->fd_config.src_port_end) {
724 cf_log_err(
conf,
"Range has invalid values for 'src_port_start' ... 'src_port_end'");
728 }
else if (
inst->fd_config.src_port_end) {
729 cf_log_err(
conf,
"Range has 'src_port_end', but is missing 'src_port_start'");
738 cf_log_perr(
conf,
"src_port_start / end range is not enough for %u worker threads",
747 inst->fd_config.reuse_port = 1;
754 if (
inst->fd_config.filename ||
inst->fd_config.path) {
755 cf_log_err(
conf,
"Cannot set 'filename' or 'path' when using 'mode=unconnected-replicate'");
762 if (
inst->fd_config.socket_type != SOCK_DGRAM) {
763 cf_log_err(
conf,
"Cannot use TCP sockets with 'mode=unconnected-replicate'");
773 inst->fd_config.reuse_port = (
inst->fd_config.src_port != 0);
778 if (
inst->fd_config.src_port_start ||
inst->fd_config.src_port_end) {
779 cf_log_err(
conf,
"Cannot set 'src_port_start' or 'src_port_end' when replicating packets");
796 if (!
inst->status_check) {
801 num_types = talloc_array_length(
inst->types);
806 .mrd =
inst->response_window,
810 .secret =
inst->secret,
811 .secret_length =
inst->secret ? talloc_array_length(
inst->secret) - 1 : 0,
818 for (i = 0; i < num_types; i++) {
821 code =
inst->types[i];
825 inst->allowed[code] =
true;
834 if (
inst->status_check) {
836 cf_log_warn(
conf,
"Ignoring 'status_check = %s' due to 'mode = replicate'",
838 inst->status_check =
false;
842 cf_log_warn(
conf,
"Ignoring 'status_check = %s' due to 'mode' setting",
844 inst->status_check =
false;
854 if (
inst->status_check) {
856 inst->allowed[
inst->status_check] =
true;
858 }
else if (!
inst->allowed[
inst->status_check]) {
859 cf_log_err(
conf,
"Using 'status_check = %s' requires also 'type = %s'",
870 if (
inst->fd_config.filename) {
872 inst->status_check = 0;
879 if (
inst->fd_config.filename ||
inst->fd_config.path) {
880 inst->max_send_coalesce = 1;
883 inst->trunk_conf.req_pool_headers = 4;
884 inst->trunk_conf.req_pool_size = 1024 +
sizeof(
fr_pair_t) + 20;
886 if (
inst->trunk_conf.conn_triggers) {
891 .module = mctx->
mi->module->
name,
900 args.server = server;
901 args.port =
inst->fd_config.dst_port;
1005 switch (
inst->mode) {
1035 PERROR(
"Failed initialising protocol library");
1072 .thread_inst_type =
"bio_thread_t",
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define L(_str)
Helper for initialising arrays of string literals.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
#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
char const * name2
Second identifier for CONF_SECTION.
#define cf_section_rules_push(_cs, _rule)
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
#define cf_section_rule_push(_cs, _rule)
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_REF(_struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_log_info(_cf, _fmt,...)
#define cf_log_perr(_cf, _fmt,...)
#define cf_log_warn(_cf, _fmt,...)
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
@ FR_RADIUS_CODE_DISCONNECT_REQUEST
RFC3575/RFC5176 - Disconnect-Request.
@ FR_RADIUS_CODE_MAX
Maximum possible protocol code.
@ FR_RADIUS_CODE_STATUS_SERVER
RFC2865/RFC5997 - Status Server (request)
@ FR_RADIUS_CODE_COA_REQUEST
RFC3575/RFC5176 - CoA-Request.
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
fr_value_box_t const * value
Enum value (what name maps to).
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
Value of an enumerated attribute.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
const conf_parser_t fr_bio_fd_client_config[]
int fr_bio_fd_check_config(fr_bio_fd_config_t const *cfg)
Checks the configuration without modifying anything.
bool active
for dynamic clients
bool dynamic
Whether the client was dynamically defined.
Describes a host allowed to send packets to the server.
int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, map_validate_t validate, void *uctx, unsigned int max)
Convert a config section into an attribute map.
main_config_t const * main_config
Main server configuration.
uint32_t max_workers
for the scheduler
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
int unlang_fixup_update(map_t *map, void *ctx)
Validate and fixup a map that's part of an update section.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
module_instance_t * mi
Module instance to detach.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
static int mod_enqueue(bio_request_t **p_u, fr_retry_config_t const **p_retry_config, rlm_radius_t const *inst, trunk_t *trunk, request_t *request)
static void mod_retry(module_ctx_t const *mctx, request_t *request, fr_retry_t const *retry)
Handle module retries.
bio_handle_ctx_t ctx
common struct for home servers and BIO handles
static xlat_action_t xlat_radius_replicate(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
static xlat_action_t xlat_radius_client(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
trunk_t * trunk
trunk handler
static unlang_action_t mod_resume(unlang_result_t *p_result, module_ctx_t const *mctx, UNUSED request_t *request)
Resume execution of the request, returning the rcode set during trunk execution.
static xlat_arg_parser_t const xlat_radius_send_args[]
Connect request_t to local tracking structure.
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.
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.
fr_pair_list_t * fr_pair_list_alloc(TALLOC_CTX *ctx)
Allocate a new pair list on the heap.
static const conf_parser_t config[]
size_t fr_radius_require_ma_table_len
int fr_radius_global_init(void)
void fr_radius_global_free(void)
fr_table_num_sorted_t const fr_radius_require_ma_table[]
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Functions to support RADIUS bio handlers.
static fr_bio_fd_config_t fd_config
#define RADIUS_MAX_ATTRIBUTES
uint32_t fr_rand(void)
Return a 32-bit random number.
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_NOOP
fr_dict_attr_t const * request_attr_request
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static conf_parser_t coa_config[]
static conf_parser_t disconnect_config[]
static int status_check_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int mod_detach(module_detach_ctx_t const *mctx)
static int mod_load(void)
static fr_dict_attr_t const * attr_packet_type
static fr_dict_attr_t const * attr_user_password
static fr_dict_attr_t const * attr_eap_message
static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static conf_parser_t const pool_config[]
static fr_dict_attr_t const * attr_chap_password
static int status_check_verify(map_t *map, void *ctx)
static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Send packets outbound.
static fr_dict_t const * dict_radius
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static fr_dict_attr_t const * attr_chap_challenge
static conf_parser_t status_config[]
fr_dict_attr_autoload_t rlm_radius_dict_attr[]
static fr_dict_attr_t const * attr_extended_attribute_1
static fr_dict_attr_t const * attr_error_cause
static void mod_unload(void)
static fr_dict_attr_t const * attr_proxy_state
static int radius_fixups(rlm_radius_t const *inst, request_t *request)
Do any RADIUS-layer fixups for proxying.
static fr_dict_attr_t const * attr_nas_identifier
static conf_parser_t const type_interval_config[FR_RADIUS_CODE_MAX]
static conf_parser_t auth_config[]
static int mode_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
fr_dict_autoload_t rlm_radius_dict[]
static conf_parser_t const transport_config[]
static int status_check_update_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static fr_dict_attr_t const * attr_original_packet_code
static fr_dict_attr_t const * attr_event_timestamp
static conf_parser_t const status_check_update_config[]
static fr_dict_attr_t const * attr_response_length
static int mod_instantiate(module_inst_ctx_t const *mctx)
static conf_parser_t const status_check_config[]
static size_t mode_names_len
static fr_table_num_sorted_t mode_names[]
static conf_parser_t const module_config[]
static conf_parser_t const connected_config[]
static fr_dict_attr_t const * attr_message_authenticator
static conf_parser_t acct_config[]
struct rlm_radius_s rlm_radius_t
@ RLM_RADIUS_MODE_XLAT_PROXY
radius.sendto.ipaddr(), but we do look for a reply.
@ RLM_RADIUS_MODE_INVALID
@ RLM_RADIUS_MODE_PROXY
we proxy to one home server
@ RLM_RADIUS_MODE_REPLICATE
to a particular destination
@ RLM_RADIUS_MODE_UNCONNECTED_REPLICATE
radius.sendto.ipaddr(), but we don't look for a reply
@ RLM_RADIUS_MODE_CLIENT
we are a client to one home server
static conf_parser_t retry_config[]
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
char const * name
Instance name e.g. user_database.
CONF_SECTION * conf
Module's instance configuration.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
#define pair_append_request(_attr, _da)
Allocate and append a fr_pair_t to the request list.
#define tmpl_is_xlat(vpt)
#define tmpl_is_attr(vpt)
#define tmpl_is_data(vpt)
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
@ TMPL_ATTR_LIST_FORBID
Attribute refs are forbidden from having a list.
Optional arguments passed to vp_tmpl functions.
fr_client_t * client_from_request(request_t *request)
Search up a list of requests trying to locate one which has a client.
unlang_action_t unlang_module_yield_to_retry(request_t *request, module_method_t resume, unlang_module_retry_t retry, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx, fr_retry_config_t const *retry_cfg)
Yield a request back to the interpreter, with retries.
static void mod_signal(module_ctx_t const *mctx, request_t *request, UNUSED fr_signal_t action)
Cancel a call to a submodule.
eap_aka_sim_process_conf_t * inst
eap_type_t type
The preferred EAP-Type of this instance of the EAP-SIM/AKA/AKA' state machine.
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
CONF_ITEM * ci
Config item that the map was created from.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Stores an attribute, a value and various bits of other data.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
An element in a lexicographically sorted array of name to num mappings.
#define talloc_get_type_abort_const
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_ispos(_a)
int module_trigger_args_build(TALLOC_CTX *ctx, fr_pair_list_t *list, CONF_SECTION *cs, module_trigger_args_t *args)
Build trigger args pair list for modules.
Common values used by modules when building trigger args.
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
bool xlat_impure_func(xlat_exp_head_t const *head)
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
struct value_pair_s fr_pair_t
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
#define fr_box_ipaddr(_val)
static size_t char ** out
#define FR_VALUE_BOX_SAFE_FOR_ANY
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.