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:
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
#include <collections/hashtable.h>
|
#include <collections/hashtable.h>
|
||||||
|
#include <threading/rwlock.h>
|
||||||
|
|
||||||
typedef struct private_eap_simaka_pseudonym_provider_t private_eap_simaka_pseudonym_provider_t;
|
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 for pseudonyms/reauth identities
|
||||||
*/
|
*/
|
||||||
rng_t *rng;
|
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;
|
identification_t *permanent;
|
||||||
|
|
||||||
|
this->lock->read_lock(this->lock);
|
||||||
permanent = this->permanent->get(this->permanent, id);
|
permanent = this->permanent->get(this->permanent, id);
|
||||||
if (permanent)
|
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;
|
identification_t *pseudonym, *permanent;
|
||||||
|
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
|
|
||||||
/* remove old entry */
|
/* remove old entry */
|
||||||
pseudonym = this->pseudonym->remove(this->pseudonym, id);
|
pseudonym = this->pseudonym->remove(this->pseudonym, id);
|
||||||
if (pseudonym)
|
if (pseudonym)
|
||||||
@@ -113,6 +123,7 @@ METHOD(simaka_provider_t, gen_pseudonym, identification_t*,
|
|||||||
pseudonym = gen_identity(this);
|
pseudonym = gen_identity(this);
|
||||||
if (!pseudonym)
|
if (!pseudonym)
|
||||||
{
|
{
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
DBG1(DBG_CFG, "failed to generate pseudonym");
|
DBG1(DBG_CFG, "failed to generate pseudonym");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -121,8 +132,10 @@ METHOD(simaka_provider_t, gen_pseudonym, identification_t*,
|
|||||||
id = id->clone(id);
|
id = id->clone(id);
|
||||||
this->pseudonym->put(this->pseudonym, id, pseudonym);
|
this->pseudonym->put(this->pseudonym, id, pseudonym);
|
||||||
this->permanent->put(this->permanent, pseudonym, id);
|
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,
|
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->pseudonym->destroy(this->pseudonym);
|
||||||
this->permanent->destroy(this->permanent);
|
this->permanent->destroy(this->permanent);
|
||||||
this->rng->destroy(this->rng);
|
this->lock->destroy(this->lock);
|
||||||
|
DESTROY_IF(this->rng);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,16 +186,16 @@ eap_simaka_pseudonym_provider_t *eap_simaka_pseudonym_provider_create()
|
|||||||
},
|
},
|
||||||
.destroy = _destroy,
|
.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),
|
.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
|
||||||
|
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
|
||||||
);
|
);
|
||||||
if (!this->rng)
|
if (!this->rng)
|
||||||
{
|
{
|
||||||
free(this);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
this->pseudonym = hashtable_create((void*)hash, (void*)equals, 0);
|
|
||||||
this->permanent = hashtable_create((void*)hash, (void*)equals, 0);
|
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user