]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add provisions for status-checks as normal packets
authorAlan T. DeKok <aland@freeradius.org>
Wed, 30 Aug 2017 01:37:12 +0000 (21:37 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 30 Aug 2017 01:37:12 +0000 (21:37 -0400)
src/modules/rlm_radius/rlm_radius.c
src/modules/rlm_radius/rlm_radius.h

index f0c8176b0dfc51994615945b7aa358e4dc2e582c..9037f4568a259eab63cda51fdd50b96082d729fa 100644 (file)
 RCSID("$Id$")
 
 #include <freeradius-devel/io/application.h>
+#include <freeradius-devel/modpriv.h>
 #include <freeradius-devel/rad_assert.h>
 
 #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.
+                */
        }
 
        /*
index b6c4b3278383f40e2cbc6ebb5efcee210ae53c78..b8251c6672394500c079182c92338b6d373f1d91 100644 (file)
@@ -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];
 };