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

This also protects access to the RNG, which is not always thread-safe.

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 e53e2c7ff6
commit 0b5143ae04
@@ -18,6 +18,7 @@
#include <utils/debug.h>
#include <collections/hashtable.h>
#include <threading/rwlock.h>
typedef struct private_eap_simaka_pseudonym_provider_t private_eap_simaka_pseudonym_provider_t;
@@ -45,6 +46,11 @@ struct private_eap_simaka_pseudonym_provider_t {
* RNG for pseudonyms/reauth identities
*/
rng_t *rng;
/**
* Lock for pseudonym mappings
*/
rwlock_t *lock;
};
/**
@@ -68,12 +74,14 @@ METHOD(simaka_provider_t, is_pseudonym, identification_t*,
{
identification_t *permanent;
this->lock->read_lock(this->lock);
permanent = this->permanent->get(this->permanent, id);
if (permanent)
{
return permanent->clone(permanent);
permanent = permanent->clone(permanent);
}
return NULL;
this->lock->unlock(this->lock);
return permanent;
}
/**
@@ -98,6 +106,8 @@ METHOD(simaka_provider_t, gen_pseudonym, identification_t*,
{
identification_t *pseudonym, *permanent;
this->lock->write_lock(this->lock);
/* remove old entry */
pseudonym = this->pseudonym->remove(this->pseudonym, id);
if (pseudonym)
@@ -113,6 +123,7 @@ METHOD(simaka_provider_t, gen_pseudonym, identification_t*,
pseudonym = gen_identity(this);
if (!pseudonym)
{
this->lock->unlock(this->lock);
DBG1(DBG_CFG, "failed to generate pseudonym");
return NULL;
}
@@ -121,8 +132,10 @@ METHOD(simaka_provider_t, gen_pseudonym, identification_t*,
id = id->clone(id);
this->pseudonym->put(this->pseudonym, id, pseudonym);
this->permanent->put(this->permanent, pseudonym, id);
pseudonym = pseudonym->clone(pseudonym);
return pseudonym->clone(pseudonym);
this->lock->unlock(this->lock);
return pseudonym;
}
METHOD(eap_simaka_pseudonym_provider_t, destroy, void,
@@ -148,7 +161,8 @@ METHOD(eap_simaka_pseudonym_provider_t, destroy, void,
this->pseudonym->destroy(this->pseudonym);
this->permanent->destroy(this->permanent);
this->rng->destroy(this->rng);
this->lock->destroy(this->lock);
DESTROY_IF(this->rng);
free(this);
}
@@ -172,16 +186,16 @@ eap_simaka_pseudonym_provider_t *eap_simaka_pseudonym_provider_create()
},
.destroy = _destroy,
},
.pseudonym = hashtable_create((void*)hash, (void*)equals, 0),
.permanent = hashtable_create((void*)hash, (void*)equals, 0),
.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
if (!this->rng)
{
free(this);
destroy(this);
return NULL;
}
this->pseudonym = hashtable_create((void*)hash, (void*)equals, 0);
this->permanent = hashtable_create((void*)hash, (void*)equals, 0);
return &this->public;
}