}
}
} else { /* packet was EAP identity */
- handler = eap_handler_alloc(inst);
+ handler = eap_handler_alloc(inst, request);
if (!handler) {
goto error;
}
PROCESS
} operation_t;
-
/*
* eap_handler_t is the interface for any EAP-Type.
* Each handler contains information for one specific EAP-Type.
char const *identity; //!< User name from EAP-Identity
+ char const *dedup; //!< dedup key
+
EAP_DS *prev_eapds;
EAP_DS *eap_ds;
/*
* 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) {
/* 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;
}
{
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;
handler->state[2], handler->state[3],
handler->state[4], handler->state[5],
handler->state[6], handler->state[7]);
+
/*
* Delete old handler from the tree.
*/
{ "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
};
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.
}
#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;
}
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;
/* 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);