]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add dedup_key for badly behaving supplicants
authorAlan T. DeKok <aland@freeradius.org>
Thu, 23 Nov 2023 16:36:29 +0000 (11:36 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 23 Nov 2023 16:36:29 +0000 (11:36 -0500)
src/modules/rlm_eap/eap.c
src/modules/rlm_eap/eap.h
src/modules/rlm_eap/mem.c
src/modules/rlm_eap/rlm_eap.c
src/modules/rlm_eap/rlm_eap.h

index b355d8c2562efd22084cb11e6af69d62dbe2bee7..8767c9fc0bd494c05fa4a5f3c31a8b2a7fda0914 100644 (file)
@@ -1216,7 +1216,7 @@ eap_handler_t *eap_handler(rlm_eap_t *inst, eap_packet_raw_t **eap_packet_p,
                       }
               }
        } else {                /* packet was EAP identity */
-               handler = eap_handler_alloc(inst);
+               handler = eap_handler_alloc(inst, request);
                if (!handler) {
                        goto error;
                }
index 849d1c6d68975ca41b6284f2b4286040a55f6731..0724463d0abc4e34afeea9d84f6eb325b00a13fd 100644 (file)
@@ -60,7 +60,6 @@ typedef enum operation_t {
        PROCESS
 } operation_t;
 
-
 /*
  * eap_handler_t is the interface for any EAP-Type.
  * Each handler contains information for one specific EAP-Type.
@@ -105,6 +104,8 @@ typedef struct _eap_handler {
 
        char const      *identity;      //!< User name from EAP-Identity
 
+       char const      *dedup;         //!< dedup key
+
        EAP_DS          *prev_eapds;
        EAP_DS          *eap_ds;
 
index 270721bc72eebd1fd53a25e905b9558e0130329b..6ef6c5c0c41ac35dd7828212e0f97295c9245edc 100644 (file)
@@ -119,9 +119,10 @@ static int _eap_handler_free(eap_handler_t *handler)
 /*
  * Allocate a new eap_handler_t
  */
-eap_handler_t *eap_handler_alloc(rlm_eap_t *inst)
+eap_handler_t *eap_handler_alloc(rlm_eap_t *inst, REQUEST *request)
 {
-       eap_handler_t   *handler;
+       eap_handler_t   *handler, *old;
+       char buffer[256];
 
        handler = talloc_zero(NULL, eap_handler_t);
        if (!handler) {
@@ -133,6 +134,20 @@ eap_handler_t *eap_handler_alloc(rlm_eap_t *inst)
        /* Doesn't need to be inside the critical region */
        talloc_set_destructor(handler, _eap_handler_free);
 
+       if (!inst->dedup_tree) return handler;
+
+       if (radius_xlat(buffer, sizeof(buffer), request, inst->dedup_key, NULL, NULL) < 0) return handler;
+
+       handler->dedup = talloc_strdup(handler, buffer);
+
+       /*
+        *      Delete any old handler
+        */
+       PTHREAD_MUTEX_LOCK(&(inst->session_mutex));
+       old = rbtree_finddata(inst->dedup_tree, handler);
+       if (old) talloc_free(old);
+       PTHREAD_MUTEX_LOCK(&(inst->session_mutex));
+
        return handler;
 }
 
@@ -171,6 +186,8 @@ static eap_handler_t *eaplist_delete(rlm_eap_t *inst, REQUEST *request,
 {
        rbnode_t *node;
 
+       if (inst->dedup_tree) (void) rbtree_deletebydata(inst->dedup_tree, handler);
+
        node = rbtree_find(inst->session_tree, handler);
        if (!node) return NULL;
 
@@ -182,6 +199,7 @@ static eap_handler_t *eaplist_delete(rlm_eap_t *inst, REQUEST *request,
               handler->state[2], handler->state[3],
               handler->state[4], handler->state[5],
               handler->state[6], handler->state[7]);
+
        /*
         *      Delete old handler from the tree.
         */
index fbd75e9dbaae2bea224497174a3529587ce90bc1..5df527e4a1bc0a4deb91bb8c01327fa3b2057b92 100644 (file)
@@ -40,6 +40,7 @@ static const CONF_PARSER module_config[] = {
        { "cisco_accounting_username_bug", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_t, mod_accounting_username_bug), "no" },
        { "allow_empty_identities", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_eap_t, allow_empty_identities), NULL },
        { "max_sessions", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_eap_t, max_sessions), "2048" },
+       { "dedup_key", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_eap_t, dedup_key), "" },
        CONF_PARSER_TERMINATOR
 };
 
@@ -99,6 +100,21 @@ static int eap_handler_cmp(void const *a, void const *b)
        return 0;
 }
 
+/*
+ *     Compare two handlers by dedup keu
+ */
+static int dedup_cmp(void const *a, void const *b)
+{
+       eap_handler_t const *one = a;
+       eap_handler_t const *two = b;
+
+       if (!one->dedup && two->dedup) return -1;
+       if (one->dedup && !two->dedup) return +1;
+
+       if (!one->dedup && two->dedup) return 0;
+
+       return strcmp(one->dedup, two->dedup);
+}
 
 /*
  * read the config section and load all the eap authentication types present.
@@ -257,6 +273,16 @@ static int mod_instantiate(CONF_SECTION *cs, void *instance)
        }
 #endif
 
+       if (!inst->dedup_key || !*inst->dedup_key) {
+               return 0;
+       }
+
+       inst->dedup_tree = rbtree_create(NULL, dedup_cmp, NULL,  0);
+       if (!inst->dedup_tree) {
+               ERROR("rlm_eap (%s): Cannot initialize dedup tree", inst->xlat_name);
+               return -1;
+       }
+
        return 0;
 }
 
index 930b763b6a653233e027289425aceb4a5a74b28f..4d5e1fa2694d7c8b211a1f5595ea14e6571d09b6 100644 (file)
@@ -67,11 +67,15 @@ typedef struct rlm_eap {
 
        uint32_t        max_sessions;
 
+       char const      *dedup_key;
+
 #ifdef HAVE_PTHREAD_H
        pthread_mutex_t session_mutex;
        pthread_mutex_t handler_mutex;
 #endif
 
+       rbtree_t        *dedup_tree;
+
        char const      *xlat_name; /* no xlat's yet */
        fr_randctx      rand_pool;
 } rlm_eap_t;
@@ -103,7 +107,7 @@ eap_handler_t       *eap_handler(rlm_eap_t *inst, eap_packet_raw_t **eap_msg, REQUEST
 
 /* Memory Management */
 EAP_DS         *eap_ds_alloc(eap_handler_t *handler);
-eap_handler_t  *eap_handler_alloc(rlm_eap_t *inst);
+eap_handler_t  *eap_handler_alloc(rlm_eap_t *inst, REQUEST *request);
 void           eap_ds_free(EAP_DS **eap_ds);
 int            eaplist_add(rlm_eap_t *inst, eap_handler_t *handler) CC_HINT(nonnull);
 eap_handler_t  *eaplist_find(rlm_eap_t *inst, REQUEST *request, eap_packet_raw_t *eap_packet);