Protect sim card/provider/hook (un-)registration with a rwlock

This commit is contained in:
Martin Willi
2011-03-08 16:42:27 +01:00
parent f58db72482
commit 7b3bfe4b6c
@@ -17,6 +17,7 @@
#include <daemon.h> #include <daemon.h>
#include <utils/linked_list.h> #include <utils/linked_list.h>
#include <threading/rwlock.h>
typedef struct private_sim_manager_t private_sim_manager_t; typedef struct private_sim_manager_t private_sim_manager_t;
@@ -44,6 +45,11 @@ struct private_sim_manager_t {
* list of added hooks * list of added hooks
*/ */
linked_list_t *hooks; linked_list_t *hooks;
/**
* lock for lists above
*/
rwlock_t *lock;
}; };
/** /**
@@ -51,7 +57,9 @@ struct private_sim_manager_t {
*/ */
static void add_card(private_sim_manager_t *this, sim_card_t *card) static void add_card(private_sim_manager_t *this, sim_card_t *card)
{ {
this->lock->write_lock(this->lock);
this->cards->insert_last(this->cards, card); this->cards->insert_last(this->cards, card);
this->lock->unlock(this->lock);
} }
/** /**
@@ -59,7 +67,9 @@ static void add_card(private_sim_manager_t *this, sim_card_t *card)
*/ */
static void remove_card(private_sim_manager_t *this, sim_card_t *card) static void remove_card(private_sim_manager_t *this, sim_card_t *card)
{ {
this->lock->write_lock(this->lock);
this->cards->remove(this->cards, card, NULL); this->cards->remove(this->cards, card, NULL);
this->lock->unlock(this->lock);
} }
/** /**
@@ -73,17 +83,20 @@ static bool card_get_triplet(private_sim_manager_t *this, identification_t *id,
sim_card_t *card; sim_card_t *card;
int tried = 0; int tried = 0;
this->lock->read_lock(this->lock);
enumerator = this->cards->create_enumerator(this->cards); enumerator = this->cards->create_enumerator(this->cards);
while (enumerator->enumerate(enumerator, &card)) while (enumerator->enumerate(enumerator, &card))
{ {
if (card->get_triplet(card, id, rand, sres, kc)) if (card->get_triplet(card, id, rand, sres, kc))
{ {
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return TRUE; return TRUE;
} }
tried++; tried++;
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
DBG1(DBG_IKE, "tried %d SIM cards, but none has triplets for '%Y'", DBG1(DBG_IKE, "tried %d SIM cards, but none has triplets for '%Y'",
tried, id); tried, id);
return FALSE; return FALSE;
@@ -103,6 +116,7 @@ static status_t card_get_quintuplet(private_sim_manager_t *this,
status_t status = NOT_FOUND; status_t status = NOT_FOUND;
int tried = 0; int tried = 0;
this->lock->read_lock(this->lock);
enumerator = this->cards->create_enumerator(this->cards); enumerator = this->cards->create_enumerator(this->cards);
while (enumerator->enumerate(enumerator, &card)) while (enumerator->enumerate(enumerator, &card))
{ {
@@ -112,6 +126,7 @@ static status_t card_get_quintuplet(private_sim_manager_t *this,
case SUCCESS: case SUCCESS:
case INVALID_STATE: case INVALID_STATE:
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return status; return status;
case NOT_SUPPORTED: case NOT_SUPPORTED:
case FAILED: case FAILED:
@@ -121,6 +136,7 @@ static status_t card_get_quintuplet(private_sim_manager_t *this,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
DBG1(DBG_IKE, "tried %d SIM cards, but none has quintuplets for '%Y'", DBG1(DBG_IKE, "tried %d SIM cards, but none has quintuplets for '%Y'",
tried, id); tried, id);
return status; return status;
@@ -135,16 +151,19 @@ static bool card_resync(private_sim_manager_t *this, identification_t *id,
enumerator_t *enumerator; enumerator_t *enumerator;
sim_card_t *card; sim_card_t *card;
this->lock->read_lock(this->lock);
enumerator = this->cards->create_enumerator(this->cards); enumerator = this->cards->create_enumerator(this->cards);
while (enumerator->enumerate(enumerator, &card)) while (enumerator->enumerate(enumerator, &card))
{ {
if (card->resync(card, id, rand, auts)) if (card->resync(card, id, rand, auts))
{ {
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return TRUE; return TRUE;
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return FALSE; return FALSE;
} }
@@ -159,12 +178,14 @@ static void card_set_pseudonym(private_sim_manager_t *this,
DBG1(DBG_IKE, "storing pseudonym '%Y' for '%Y'", pseudonym, id); DBG1(DBG_IKE, "storing pseudonym '%Y' for '%Y'", pseudonym, id);
this->lock->read_lock(this->lock);
enumerator = this->cards->create_enumerator(this->cards); enumerator = this->cards->create_enumerator(this->cards);
while (enumerator->enumerate(enumerator, &card)) while (enumerator->enumerate(enumerator, &card))
{ {
card->set_pseudonym(card, id, pseudonym); card->set_pseudonym(card, id, pseudonym);
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
} }
/** /**
@@ -177,6 +198,7 @@ static identification_t* card_get_pseudonym(private_sim_manager_t *this,
sim_card_t *card; sim_card_t *card;
identification_t *pseudonym = NULL; identification_t *pseudonym = NULL;
this->lock->read_lock(this->lock);
enumerator = this->cards->create_enumerator(this->cards); enumerator = this->cards->create_enumerator(this->cards);
while (enumerator->enumerate(enumerator, &card)) while (enumerator->enumerate(enumerator, &card))
{ {
@@ -189,6 +211,7 @@ static identification_t* card_get_pseudonym(private_sim_manager_t *this,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return pseudonym; return pseudonym;
} }
@@ -205,12 +228,14 @@ static void card_set_reauth(private_sim_manager_t *this, identification_t *id,
DBG1(DBG_IKE, "storing next reauthentication identity '%Y' for '%Y'", DBG1(DBG_IKE, "storing next reauthentication identity '%Y' for '%Y'",
next, id); next, id);
this->lock->read_lock(this->lock);
enumerator = this->cards->create_enumerator(this->cards); enumerator = this->cards->create_enumerator(this->cards);
while (enumerator->enumerate(enumerator, &card)) while (enumerator->enumerate(enumerator, &card))
{ {
card->set_reauth(card, id, next, mk, counter); card->set_reauth(card, id, next, mk, counter);
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
} }
/** /**
@@ -224,6 +249,7 @@ static identification_t* card_get_reauth(private_sim_manager_t *this,
sim_card_t *card; sim_card_t *card;
identification_t *reauth = NULL; identification_t *reauth = NULL;
this->lock->read_lock(this->lock);
enumerator = this->cards->create_enumerator(this->cards); enumerator = this->cards->create_enumerator(this->cards);
while (enumerator->enumerate(enumerator, &card)) while (enumerator->enumerate(enumerator, &card))
{ {
@@ -236,6 +262,7 @@ static identification_t* card_get_reauth(private_sim_manager_t *this,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return reauth; return reauth;
} }
@@ -244,7 +271,9 @@ static identification_t* card_get_reauth(private_sim_manager_t *this,
*/ */
static void add_provider(private_sim_manager_t *this, sim_provider_t *provider) static void add_provider(private_sim_manager_t *this, sim_provider_t *provider)
{ {
this->lock->write_lock(this->lock);
this->providers->insert_last(this->providers, provider); this->providers->insert_last(this->providers, provider);
this->lock->unlock(this->lock);
} }
/** /**
@@ -253,7 +282,9 @@ static void add_provider(private_sim_manager_t *this, sim_provider_t *provider)
static void remove_provider(private_sim_manager_t *this, static void remove_provider(private_sim_manager_t *this,
sim_provider_t *provider) sim_provider_t *provider)
{ {
this->lock->write_lock(this->lock);
this->providers->remove(this->providers, provider, NULL); this->providers->remove(this->providers, provider, NULL);
this->lock->unlock(this->lock);
} }
/** /**
@@ -267,17 +298,20 @@ static bool provider_get_triplet(private_sim_manager_t *this,
sim_provider_t *provider; sim_provider_t *provider;
int tried = 0; int tried = 0;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers); enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &provider)) while (enumerator->enumerate(enumerator, &provider))
{ {
if (provider->get_triplet(provider, id, rand, sres, kc)) if (provider->get_triplet(provider, id, rand, sres, kc))
{ {
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return TRUE; return TRUE;
} }
tried++; tried++;
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'", DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'",
tried, id); tried, id);
return FALSE; return FALSE;
@@ -296,6 +330,7 @@ static bool provider_get_quintuplet(private_sim_manager_t *this,
sim_provider_t *provider; sim_provider_t *provider;
int tried = 0; int tried = 0;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers); enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &provider)) while (enumerator->enumerate(enumerator, &provider))
{ {
@@ -303,10 +338,12 @@ static bool provider_get_quintuplet(private_sim_manager_t *this,
ck, ik, autn)) ck, ik, autn))
{ {
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return TRUE; return TRUE;
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
DBG1(DBG_IKE, "tried %d SIM providers, but none had a quintuplet for '%Y'", DBG1(DBG_IKE, "tried %d SIM providers, but none had a quintuplet for '%Y'",
tried, id); tried, id);
return FALSE; return FALSE;
@@ -321,16 +358,19 @@ static bool provider_resync(private_sim_manager_t *this, identification_t *id,
enumerator_t *enumerator; enumerator_t *enumerator;
sim_provider_t *provider; sim_provider_t *provider;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers); enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &provider)) while (enumerator->enumerate(enumerator, &provider))
{ {
if (provider->resync(provider, id, rand, auts)) if (provider->resync(provider, id, rand, auts))
{ {
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return TRUE; return TRUE;
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return FALSE; return FALSE;
} }
@@ -344,6 +384,7 @@ static identification_t* provider_is_pseudonym(private_sim_manager_t *this,
sim_provider_t *provider; sim_provider_t *provider;
identification_t *permanent = NULL; identification_t *permanent = NULL;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers); enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &provider)) while (enumerator->enumerate(enumerator, &provider))
{ {
@@ -356,6 +397,7 @@ static identification_t* provider_is_pseudonym(private_sim_manager_t *this,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return permanent; return permanent;
} }
@@ -369,6 +411,7 @@ static identification_t* provider_gen_pseudonym(private_sim_manager_t *this,
sim_provider_t *provider; sim_provider_t *provider;
identification_t *pseudonym = NULL; identification_t *pseudonym = NULL;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers); enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &provider)) while (enumerator->enumerate(enumerator, &provider))
{ {
@@ -380,6 +423,7 @@ static identification_t* provider_gen_pseudonym(private_sim_manager_t *this,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return pseudonym; return pseudonym;
} }
@@ -394,6 +438,7 @@ static identification_t* provider_is_reauth(private_sim_manager_t *this,
sim_provider_t *provider; sim_provider_t *provider;
identification_t *permanent = NULL; identification_t *permanent = NULL;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers); enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &provider)) while (enumerator->enumerate(enumerator, &provider))
{ {
@@ -406,6 +451,7 @@ static identification_t* provider_is_reauth(private_sim_manager_t *this,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return permanent; return permanent;
} }
@@ -419,6 +465,7 @@ static identification_t* provider_gen_reauth(private_sim_manager_t *this,
sim_provider_t *provider; sim_provider_t *provider;
identification_t *reauth = NULL; identification_t *reauth = NULL;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers); enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &provider)) while (enumerator->enumerate(enumerator, &provider))
{ {
@@ -430,6 +477,7 @@ static identification_t* provider_gen_reauth(private_sim_manager_t *this,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return reauth; return reauth;
} }
@@ -438,7 +486,9 @@ static identification_t* provider_gen_reauth(private_sim_manager_t *this,
*/ */
static void add_hooks(private_sim_manager_t *this, sim_hooks_t *hooks) static void add_hooks(private_sim_manager_t *this, sim_hooks_t *hooks)
{ {
this->lock->write_lock(this->lock);
this->hooks->insert_last(this->hooks, hooks); this->hooks->insert_last(this->hooks, hooks);
this->lock->unlock(this->lock);
} }
/** /**
@@ -446,7 +496,9 @@ static void add_hooks(private_sim_manager_t *this, sim_hooks_t *hooks)
*/ */
static void remove_hooks(private_sim_manager_t *this, sim_hooks_t *hooks) static void remove_hooks(private_sim_manager_t *this, sim_hooks_t *hooks)
{ {
this->lock->write_lock(this->lock);
this->hooks->remove(this->hooks, hooks, NULL); this->hooks->remove(this->hooks, hooks, NULL);
this->lock->unlock(this->lock);
} }
/** /**
@@ -458,12 +510,14 @@ static void message_hook(private_sim_manager_t *this,
enumerator_t *enumerator; enumerator_t *enumerator;
sim_hooks_t *hooks; sim_hooks_t *hooks;
this->lock->read_lock(this->lock);
enumerator = this->hooks->create_enumerator(this->hooks); enumerator = this->hooks->create_enumerator(this->hooks);
while (enumerator->enumerate(enumerator, &hooks)) while (enumerator->enumerate(enumerator, &hooks))
{ {
hooks->message(hooks, message, inbound, decrypted); hooks->message(hooks, message, inbound, decrypted);
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
} }
/** /**
@@ -475,12 +529,14 @@ static void key_hook(private_sim_manager_t *this,
enumerator_t *enumerator; enumerator_t *enumerator;
sim_hooks_t *hooks; sim_hooks_t *hooks;
this->lock->read_lock(this->lock);
enumerator = this->hooks->create_enumerator(this->hooks); enumerator = this->hooks->create_enumerator(this->hooks);
while (enumerator->enumerate(enumerator, &hooks)) while (enumerator->enumerate(enumerator, &hooks))
{ {
hooks->keys(hooks, k_encr, k_auth); hooks->keys(hooks, k_encr, k_auth);
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
} }
/** /**
@@ -491,6 +547,7 @@ static void destroy(private_sim_manager_t *this)
this->cards->destroy(this->cards); this->cards->destroy(this->cards);
this->providers->destroy(this->providers); this->providers->destroy(this->providers);
this->hooks->destroy(this->hooks); this->hooks->destroy(this->hooks);
this->lock->destroy(this->lock);
free(this); free(this);
} }
@@ -528,6 +585,7 @@ sim_manager_t *sim_manager_create()
this->cards = linked_list_create(); this->cards = linked_list_create();
this->providers = linked_list_create(); this->providers = linked_list_create();
this->hooks = linked_list_create(); this->hooks = linked_list_create();
this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
return &this->public; return &this->public;
} }