eap-simaka-reauth: Prevent corrupting hashtables during concurrent accesses

Basically the same as the previous commit.

Fixes: edcb2dd35b ("Moved reauth/pseudonym functionality from eap-sim-file to separate plugins, usable by any SIM/AKA backend")
This commit is contained in:
Tobias Brunner
2026-07-23 10:26:08 +02:00
parent 0b5143ae04
commit 4bef380ce0
@@ -18,6 +18,7 @@
#include <daemon.h> #include <daemon.h>
#include <collections/hashtable.h> #include <collections/hashtable.h>
#include <threading/mutex.h>
typedef struct private_eap_simaka_reauth_provider_t private_eap_simaka_reauth_provider_t; typedef struct private_eap_simaka_reauth_provider_t private_eap_simaka_reauth_provider_t;
@@ -45,6 +46,11 @@ struct private_eap_simaka_reauth_provider_t {
* RNG for pseudonyms/reauth identities * RNG for pseudonyms/reauth identities
*/ */
rng_t *rng; rng_t *rng;
/**
* Lock for reauth mappings
*/
mutex_t *mutex;
}; };
/** /**
@@ -98,21 +104,27 @@ METHOD(simaka_provider_t, is_reauth, identification_t*,
identification_t *permanent; identification_t *permanent;
reauth_data_t *data; reauth_data_t *data;
this->mutex->lock(this->mutex);
/* look up permanent identity */ /* look up permanent identity */
permanent = this->permanent->get(this->permanent, id); permanent = this->permanent->get(this->permanent, id);
if (!permanent) if (!permanent)
{ {
this->mutex->unlock(this->mutex);
return NULL; return NULL;
} }
/* look up reauthentication data */ /* look up reauthentication data */
data = this->reauth->get(this->reauth, permanent); data = this->reauth->get(this->reauth, permanent);
if (!data) if (!data)
{ {
this->mutex->unlock(this->mutex);
return NULL; return NULL;
} }
*counter = ++data->counter; *counter = ++data->counter;
memcpy(mk, data->mk, HASH_SIZE_SHA1); memcpy(mk, data->mk, HASH_SIZE_SHA1);
return permanent->clone(permanent); permanent = permanent->clone(permanent);
this->mutex->unlock(this->mutex);
return permanent;
} }
METHOD(simaka_provider_t, gen_reauth, identification_t*, METHOD(simaka_provider_t, gen_reauth, identification_t*,
@@ -122,10 +134,12 @@ METHOD(simaka_provider_t, gen_reauth, identification_t*,
reauth_data_t *data; reauth_data_t *data;
identification_t *permanent, *new_id; identification_t *permanent, *new_id;
this->mutex->lock(this->mutex);
new_id = gen_identity(this); new_id = gen_identity(this);
if (!new_id) if (!new_id)
{ {
DBG1(DBG_CFG, "failed to generate identity"); DBG1(DBG_CFG, "failed to generate identity");
this->mutex->unlock(this->mutex);
return NULL; return NULL;
} }
@@ -155,7 +169,9 @@ METHOD(simaka_provider_t, gen_reauth, identification_t*,
} }
memcpy(data->mk, mk, HASH_SIZE_SHA1); memcpy(data->mk, mk, HASH_SIZE_SHA1);
return data->id->clone(data->id); new_id = data->id->clone(data->id);
this->mutex->unlock(this->mutex);
return new_id;
} }
METHOD(eap_simaka_reauth_provider_t, destroy, void, METHOD(eap_simaka_reauth_provider_t, destroy, void,
@@ -183,7 +199,8 @@ METHOD(eap_simaka_reauth_provider_t, destroy, void,
this->permanent->destroy(this->permanent); this->permanent->destroy(this->permanent);
this->reauth->destroy(this->reauth); this->reauth->destroy(this->reauth);
this->rng->destroy(this->rng); this->mutex->destroy(this->mutex);
DESTROY_IF(this->rng);
free(this); free(this);
} }
@@ -207,16 +224,16 @@ eap_simaka_reauth_provider_t *eap_simaka_reauth_provider_create()
}, },
.destroy = _destroy, .destroy = _destroy,
}, },
.permanent = hashtable_create((void*)hash, (void*)equals, 0),
.reauth = hashtable_create((void*)hash, (void*)equals, 0),
.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
); );
if (!this->rng) if (!this->rng)
{ {
free(this); destroy(this);
return NULL; return NULL;
} }
this->permanent = hashtable_create((void*)hash, (void*)equals, 0);
this->reauth = hashtable_create((void*)hash, (void*)equals, 0);
return &this->public; return &this->public;
} }