From: Alan T. DeKok Date: Wed, 30 Aug 2017 01:37:12 +0000 (-0400) Subject: add provisions for status-checks as normal packets X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=934ecd1279ce180add596d51123935fc73c5ab36;p=thirdparty%2Ffreeradius-server.git add provisions for status-checks as normal packets --- diff --git a/src/modules/rlm_radius/rlm_radius.c b/src/modules/rlm_radius/rlm_radius.c index f0c8176b0df..9037f4568a2 100644 --- a/src/modules/rlm_radius/rlm_radius.c +++ b/src/modules/rlm_radius/rlm_radius.c @@ -25,13 +25,30 @@ RCSID("$Id$") #include +#include #include #include "rlm_radius.h" static int transport_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, CONF_PARSER const *rule); static int type_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, CONF_PARSER const *rule); -static int status_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, CONF_PARSER const *rule); +static int status_check_type_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, CONF_PARSER const *rule); +static int status_check_update_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, CONF_PARSER const *rule); + +static CONF_PARSER const status_checks_config[] = { + { FR_CONF_OFFSET("type", FR_TYPE_VOID, rlm_radius_t, status_check), + .func = status_check_type_parse }, + + CONF_PARSER_TERMINATOR +}; + +static CONF_PARSER const status_check_update_config[] = { + { FR_CONF_OFFSET("update", FR_TYPE_SUBSECTION | FR_TYPE_REQUIRED, rlm_radius_t, status_check_map), + .ident2 = CF_IDENT_ANY, + .func = status_check_update_parse }, + + CONF_PARSER_TERMINATOR +}; static CONF_PARSER const connection_config[] = { { FR_CONF_OFFSET("connect_timeout", FR_TYPE_TIMEVAL, rlm_radius_t, connection_timeout), @@ -103,15 +120,14 @@ static CONF_PARSER const module_config[] = { { FR_CONF_OFFSET("type", FR_TYPE_UINT32 | FR_TYPE_MULTI | FR_TYPE_NOT_EMPTY | FR_TYPE_REQUIRED, rlm_radius_t, types), .func = type_parse }, - { FR_CONF_OFFSET("status_check", FR_TYPE_VOID, rlm_radius_t, status_check), - .func = status_parse }, - { FR_CONF_OFFSET("replicate", FR_TYPE_BOOL, rlm_radius_t, replicate) }, { FR_CONF_OFFSET("synchronous", FR_TYPE_BOOL, rlm_radius_t, synchronous) }, { FR_CONF_OFFSET("no_connection_fail", FR_TYPE_BOOL, rlm_radius_t, no_connection_fail) }, + { FR_CONF_POINTER("status_checks", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) status_checks_config }, + { FR_CONF_POINTER("connection", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) connection_config }, CONF_PARSER_TERMINATOR @@ -126,18 +142,6 @@ static CONF_PARSER const type_interval_config[FR_MAX_PACKET_CODE] = { [FR_CODE_DISCONNECT_REQUEST] = { FR_CONF_POINTER("Disconnect-Request", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) disconnect_config }, }; -#if 0 -static CONF_PARSER const status_check_config[FR_MAX_PACKET_CODE] = { - [FR_CODE_ACCESS_REQUEST] = { FR_CONF_POINTER("Access-Request", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) auth_check_config }, - - [FR_CODE_ACCOUNTING_REQUEST] = { FR_CONF_POINTER("Accounting-Request", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) acct_check_config }, - [FR_CODE_STATUS_SERVER] = { FR_CONF_POINTER("Status-Server", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) status_check_config }, - [FR_CODE_COA_REQUEST] = { FR_CONF_POINTER("CoA-Request", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) coa_check_config }, - [FR_CODE_DISCONNECT_REQUEST] = { FR_CONF_POINTER("Disconnect-Request", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) disconnect_check_config }, -}; -#endif - - /** Set which types of packets we can parse * * @param[in] ctx to allocate data in (instance of rlm_radius). @@ -238,14 +242,14 @@ static int transport_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED CON /** Allow for Status-Server ping checks * * @param[in] ctx to allocate data in (instance of proto_radius). - * @param[out] out Where to write a dl_instance_t containing the module handle and instance. + * @param[out] out Where to write our parsed data * @param[in] ci #CONF_PAIR specifying the name of the type module. * @param[in] rule unused. * @return * - 0 on success. * - -1 on failure. */ -static int status_parse(UNUSED TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule) +static int status_check_type_parse(UNUSED TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule) { char const *type_str = cf_pair_value(cf_item_to_pair(ci)); CONF_SECTION *cs = cf_item_to_section(cf_parent(ci)); @@ -253,11 +257,6 @@ static int status_parse(UNUSED TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED fr_dict_enum_t const *type_enum; uint32_t code; - /* - * Must be the RADIUS module - */ - rad_assert(cs && (strcmp(cf_section_name1(cs), "radius") == 0)); - da = fr_dict_attr_by_name(NULL, "Packet-Type"); if (!da) { ERROR("Missing definiton for Packet-Type"); @@ -286,21 +285,71 @@ static int status_parse(UNUSED TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED (!type_interval_config[code].name)) goto invalid_code; /* - * This wasn't allowed by 'type = ..', so we add it here - * manually. + * Add irt / mrt / mrd / mrc parsing, in the parent + * configuration section. */ - if (code == FR_CODE_STATUS_SERVER) { - cf_section_rule_push(cs, &type_interval_config[FR_CODE_STATUS_SERVER]); + cf_section_rule_push(cf_item_to_section(cf_parent(cs)), &type_interval_config[code]); + + memcpy(out, &code, sizeof(code)); + + /* + * Nothing more to do here, so we stop. + */ + if (code == FR_CODE_STATUS_SERVER) return 0; + + cf_section_rule_push(cs, status_check_update_config); + + return 0; +} + +/** Allow the admin to set packet contents for Status-Server ping checks + * + * @param[in] ctx to allocate data in (instance of proto_radius). + * @param[out] out Where to write our parsed data + * @param[in] ci #CONF_SECTION specifying the things to update + * @param[in] rule unused. + * @return + * - 0 on success. + * - -1 on failure. + */ +static int status_check_update_parse(UNUSED TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule) +{ + int rcode; + CONF_SECTION *cs; + char const *name2; + vp_map_t *head = NULL; + + rad_assert(cf_item_is_section(ci)); + + cs = cf_item_to_section(ci); + + name2 = cf_section_name2(cs); + if (!name2 || (strcmp(name2, "request") != 0)) { + cf_log_err(cs, "You must specify 'request' as the destination list"); + return -1; } - // @todo - push type_check_config rules + /* + * Compile the "update" section. + */ + rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, unlang_fixup_update, NULL, 128); + if (rcode < 0) return -1; /* message already printed */ + if (!head) { + cf_log_err(cs, "'update' sections cannot be empty"); + return -1; + } - memcpy(out, &code, sizeof(code)); + /* + * Rely on "bootstrap" to do sanity checks between 'type + * = Access-Request', and 'update' containing passwords. + */ + memcpy(out, &head, sizeof(head)); return 0; } + /** Free an rlm_radius_link_t * * Unlink it from the running list, and remove it from the @@ -555,11 +604,18 @@ static int mod_bootstrap(void *instance, CONF_SECTION *conf) * If we have status_check = packet, then 'packet' MUST either be * Status-Server, or it MUST be one of the allowed packet types for this connection. */ - if (inst->status_check && (inst->status_check != FR_CODE_STATUS_SERVER) && - !inst->allowed[inst->status_check]) { - cf_log_err(conf, "Using 'status_check = %s' requires also 'type = %s'", - fr_packet_codes[inst->status_check], fr_packet_codes[inst->status_check]); - return -1; + if (inst->status_check && inst->status_check != FR_CODE_STATUS_SERVER) { + if (!inst->allowed[inst->status_check]) { + cf_log_err(conf, "Using 'status_check = %s' requires also 'type = %s'", + fr_packet_codes[inst->status_check], fr_packet_codes[inst->status_check]); + return -1; + } + + /* + * @todo - check the contents of the "update" + * section, to be sure that (e.g.) Access-Request + * contains User-Name, etc. + */ } /* diff --git a/src/modules/rlm_radius/rlm_radius.h b/src/modules/rlm_radius/rlm_radius.h index b6c4b327838..b8251c66723 100644 --- a/src/modules/rlm_radius/rlm_radius.h +++ b/src/modules/rlm_radius/rlm_radius.h @@ -92,6 +92,8 @@ struct rlm_radius_t { uint32_t *types; //!< array of allowed packet types uint32_t status_check; //!< code of status-check type + vp_map_t *status_check_map; //!< attributes for the status-server checks + int allowed[FR_MAX_PACKET_CODE]; rlm_radius_retry_t retry[FR_MAX_PACKET_CODE]; };