Moved card/provider enumeration to SIM manager, providing wrapped functions for both SIM and AKA plugins
This commit is contained in:
@@ -81,7 +81,6 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
|
||||
simaka_message_t *message;
|
||||
enumerator_t *enumerator;
|
||||
simaka_attribute_t type;
|
||||
sim_card_t *card;
|
||||
chunk_t data, rand = chunk_empty, autn = chunk_empty, mk;
|
||||
u_char res[AKA_RES_LEN], ck[AKA_CK_LEN], ik[AKA_IK_LEN], auts[AKA_AUTS_LEN];
|
||||
status_t status = NOT_FOUND;
|
||||
@@ -116,20 +115,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this,
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
enumerator = charon->sim->create_card_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &card))
|
||||
{
|
||||
status = card->get_quintuplet(card, this->peer, rand.ptr, autn.ptr,
|
||||
ck, ik, res);
|
||||
if (status != FAILED)
|
||||
{ /* try next on error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
status = charon->sim->card_get_quintuplet(charon->sim, this->peer,
|
||||
rand.ptr, autn.ptr, ck, ik, res);
|
||||
if (status == INVALID_STATE &&
|
||||
card->resync(card, this->peer, rand.ptr, auts))
|
||||
charon->sim->card_resync(charon->sim, this->peer, rand.ptr, auts))
|
||||
{
|
||||
DBG1(DBG_IKE, "received SQN invalid, sending %N",
|
||||
simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE);
|
||||
|
||||
@@ -94,31 +94,17 @@ static bool attribute_skippable(simaka_attribute_t attribute)
|
||||
static status_t initiate(private_eap_aka_server_t *this, eap_payload_t **out)
|
||||
{
|
||||
simaka_message_t *message;
|
||||
enumerator_t *enumerator;
|
||||
sim_provider_t *provider;
|
||||
char rand[AKA_RAND_LEN], xres[AKA_RES_LEN];
|
||||
char ck[AKA_CK_LEN], ik[AKA_IK_LEN], autn[AKA_AUTN_LEN];
|
||||
chunk_t data, mk;
|
||||
bool found = FALSE;
|
||||
|
||||
enumerator = charon->sim->create_provider_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &provider))
|
||||
{
|
||||
if (provider->get_quintuplet(provider, this->peer,
|
||||
rand, xres, ck, ik, autn))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (!found)
|
||||
if (!charon->sim->provider_get_quintuplet(charon->sim, this->peer,
|
||||
rand, xres, ck, ik, autn))
|
||||
{
|
||||
DBG1(DBG_IKE, "no AKA provider found with quintuplets for '%Y'",
|
||||
this->peer);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN),
|
||||
chunk_create(ck, AKA_CK_LEN));
|
||||
free(this->msk.ptr);
|
||||
@@ -197,11 +183,9 @@ static status_t process_challenge(private_eap_aka_server_t *this,
|
||||
static status_t process_synchronize(private_eap_aka_server_t *this,
|
||||
simaka_message_t *in, eap_payload_t **out)
|
||||
{
|
||||
sim_provider_t *provider;
|
||||
enumerator_t *enumerator;
|
||||
simaka_attribute_t type;
|
||||
chunk_t data, auts = chunk_empty;
|
||||
bool found = FALSE;
|
||||
|
||||
if (this->synchronized)
|
||||
{
|
||||
@@ -239,18 +223,8 @@ static status_t process_synchronize(private_eap_aka_server_t *this,
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
enumerator = charon->sim->create_provider_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &provider))
|
||||
{
|
||||
if (provider->resync(provider, this->peer, this->rand.ptr, auts.ptr))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!found)
|
||||
if (!charon->sim->provider_resync(charon->sim, this->peer,
|
||||
this->rand.ptr, auts.ptr))
|
||||
{
|
||||
DBG1(DBG_IKE, "no AKA provider found supporting "
|
||||
"resynchronization for '%Y'", this->peer);
|
||||
|
||||
@@ -94,124 +94,34 @@ struct private_eap_sim_peer_t {
|
||||
/* version of SIM protocol we speak */
|
||||
static chunk_t version = chunk_from_chars(0x00,0x01);
|
||||
|
||||
/**
|
||||
* Read a triplet from the SIM card
|
||||
*/
|
||||
static bool get_triplet(private_eap_sim_peer_t *this, identification_t *peer,
|
||||
char *rand, char *sres, char *kc)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_card_t *card;
|
||||
bool success = FALSE;
|
||||
|
||||
enumerator = charon->sim->create_card_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &card))
|
||||
{
|
||||
if (card->get_triplet(card, peer, rand, sres, kc))
|
||||
{
|
||||
success = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (!success)
|
||||
{
|
||||
DBG1(DBG_IKE, "no SIM card found with triplets for '%Y'", peer);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a stored reauthentication identity on a SIM card
|
||||
*/
|
||||
static identification_t *get_reauth(private_eap_sim_peer_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_card_t *card;
|
||||
identification_t *reauth = NULL;
|
||||
|
||||
enumerator = charon->sim->create_card_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &card))
|
||||
{
|
||||
reauth = card->get_reauth(card, this->permanent,
|
||||
this->mk, &this->counter);
|
||||
if (reauth)
|
||||
{
|
||||
DBG1(DBG_IKE, "using stored reauthentication identity '%Y' "
|
||||
"instead of '%Y'", reauth, this->permanent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return reauth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store received next fast reauthentication identity, along with mk/counter
|
||||
*/
|
||||
static void set_reauth(private_eap_sim_peer_t *this, chunk_t data)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_card_t *card;
|
||||
identification_t *reauth;
|
||||
char buf[data.len + 1];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%.*s", data.len, data.ptr);
|
||||
reauth = identification_create_from_string(buf);
|
||||
DBG1(DBG_IKE, "received next reauthentication identity '%Y'", reauth);
|
||||
|
||||
enumerator = charon->sim->create_card_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &card))
|
||||
{
|
||||
card->set_reauth(card, this->permanent, reauth, this->mk, this->counter);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
charon->sim->card_set_reauth(charon->sim, this->permanent, reauth,
|
||||
this->mk, this->counter);
|
||||
reauth->destroy(reauth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a stored pseudonym on a SIM card
|
||||
*/
|
||||
static identification_t *get_pseudonym(private_eap_sim_peer_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_card_t *card;
|
||||
identification_t *pseudonym = NULL;
|
||||
|
||||
enumerator = charon->sim->create_card_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &card))
|
||||
{
|
||||
pseudonym = card->get_pseudonym(card, this->permanent);
|
||||
if (pseudonym)
|
||||
{
|
||||
DBG1(DBG_IKE, "using stored pseudonym identity '%Y' "
|
||||
"instead of '%Y'", pseudonym, this->permanent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return pseudonym;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a pseudonym in a SIM card
|
||||
*/
|
||||
static void set_pseudonym(private_eap_sim_peer_t *this, chunk_t data)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_card_t *card;
|
||||
identification_t *pseudonym;
|
||||
char buf[data.len + 1];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%.*s", data.len, data.ptr);
|
||||
pseudonym = identification_create_from_string(buf);
|
||||
DBG1(DBG_IKE, "received pseudonym '%Y' for next authentication", pseudonym);
|
||||
enumerator = charon->sim->create_card_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &card))
|
||||
{
|
||||
card->set_pseudonym(card, this->permanent, pseudonym);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
charon->sim->card_set_pseudonym(charon->sim, this->permanent, pseudonym);
|
||||
pseudonym->destroy(pseudonym);
|
||||
}
|
||||
|
||||
@@ -306,7 +216,8 @@ static status_t process_start(private_eap_sim_peer_t *this,
|
||||
switch (id_req)
|
||||
{
|
||||
case AT_ANY_ID_REQ:
|
||||
this->reauth = get_reauth(this);
|
||||
this->reauth = charon->sim->card_get_reauth(charon->sim,
|
||||
this->permanent, this->mk, &this->counter);
|
||||
if (this->reauth)
|
||||
{
|
||||
id = this->reauth->get_encoding(this->reauth);
|
||||
@@ -314,7 +225,8 @@ static status_t process_start(private_eap_sim_peer_t *this,
|
||||
}
|
||||
/* FALL */
|
||||
case AT_FULLAUTH_ID_REQ:
|
||||
this->pseudonym = get_pseudonym(this);
|
||||
this->pseudonym = charon->sim->card_get_pseudonym(charon->sim,
|
||||
this->permanent);
|
||||
if (this->pseudonym)
|
||||
{
|
||||
id = this->pseudonym->get_encoding(this->pseudonym);
|
||||
@@ -405,7 +317,8 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
|
||||
sreses = sres = chunk_alloca(rands.len / 4);
|
||||
while (rands.len >= SIM_RAND_LEN)
|
||||
{
|
||||
if (!get_triplet(this, this->permanent, rands.ptr, sres.ptr, kc.ptr))
|
||||
if (!charon->sim->card_get_triplet(charon->sim, this->permanent,
|
||||
rands.ptr, sres.ptr, kc.ptr))
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to get EAP-SIM triplet");
|
||||
*out = create_client_error(this, in->get_identifier(in),
|
||||
|
||||
@@ -107,126 +107,6 @@ struct private_eap_sim_server_t {
|
||||
/* version of SIM protocol we speak */
|
||||
static chunk_t version = chunk_from_chars(0x00,0x01);
|
||||
|
||||
/**
|
||||
* Fetch a triplet from a provider
|
||||
*/
|
||||
static bool get_triplet(private_eap_sim_server_t *this, identification_t *peer,
|
||||
char *rand, char *sres, char *kc)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_provider_t *provider;
|
||||
int tried = 0;
|
||||
|
||||
enumerator = charon->sim->create_provider_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &provider))
|
||||
{
|
||||
if (provider->get_triplet(provider, peer, rand, sres, kc))
|
||||
{
|
||||
enumerator->destroy(enumerator);
|
||||
return TRUE;
|
||||
}
|
||||
tried++;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'",
|
||||
tried, peer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new reauthentication identity for next fast reauthentication
|
||||
*/
|
||||
static identification_t* gen_reauth(private_eap_sim_server_t *this,
|
||||
char mk[HASH_SIZE_SHA1])
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_provider_t *provider;
|
||||
identification_t *reauth = NULL;
|
||||
|
||||
enumerator = charon->sim->create_provider_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &provider))
|
||||
{
|
||||
reauth = provider->gen_reauth(provider, this->permanent, mk);
|
||||
if (reauth)
|
||||
{
|
||||
DBG1(DBG_IKE, "proposing new reauthentication identity '%Y'", reauth);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return reauth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an identity is a known reauthentication identity
|
||||
*/
|
||||
static identification_t* is_reauth(private_eap_sim_server_t *this,
|
||||
identification_t *id, char mk[HASH_SIZE_SHA1],
|
||||
u_int16_t *counter)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_provider_t *provider;
|
||||
identification_t *permanent = NULL;
|
||||
|
||||
enumerator = charon->sim->create_provider_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &provider))
|
||||
{
|
||||
permanent = provider->is_reauth(provider, id, mk, counter);
|
||||
if (permanent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return permanent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new pseudonym for next authentication
|
||||
*/
|
||||
static identification_t* gen_pseudonym(private_eap_sim_server_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_provider_t *provider;
|
||||
identification_t *pseudonym = NULL;
|
||||
|
||||
enumerator = charon->sim->create_provider_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &provider))
|
||||
{
|
||||
pseudonym = provider->gen_pseudonym(provider, this->permanent);
|
||||
if (pseudonym)
|
||||
{
|
||||
DBG1(DBG_IKE, "proposing new pseudonym '%Y'", pseudonym);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return pseudonym;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an identity is a known pseudonym
|
||||
*/
|
||||
static identification_t* is_pseudonym(private_eap_sim_server_t *this,
|
||||
identification_t *pseudonym)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sim_provider_t *provider;
|
||||
identification_t *permanent = NULL;
|
||||
|
||||
enumerator = charon->sim->create_provider_enumerator(charon->sim);
|
||||
while (enumerator->enumerate(enumerator, &provider))
|
||||
{
|
||||
permanent = provider->is_pseudonym(provider, pseudonym);
|
||||
if (permanent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return permanent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of eap_method_t.initiate
|
||||
*/
|
||||
@@ -285,7 +165,7 @@ static status_t reauthenticate(private_eap_sim_server_t *this,
|
||||
SIM_REAUTHENTICATION, this->crypto);
|
||||
message->add_attribute(message, AT_COUNTER, this->counter);
|
||||
message->add_attribute(message, AT_NONCE_S, this->nonce);
|
||||
next = gen_reauth(this, mk);
|
||||
next = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk);
|
||||
if (next)
|
||||
{
|
||||
message->add_attribute(message, AT_NEXT_REAUTH_ID,
|
||||
@@ -424,7 +304,8 @@ static status_t process_start(private_eap_sim_server_t *this,
|
||||
char mk[HASH_SIZE_SHA1];
|
||||
u_int16_t counter;
|
||||
|
||||
permanent = is_reauth(this, id, mk, &counter);
|
||||
permanent = charon->sim->provider_is_reauth(charon->sim, id,
|
||||
mk, &counter);
|
||||
if (permanent)
|
||||
{
|
||||
DBG1(DBG_IKE, "received reauthentication identity '%Y' "
|
||||
@@ -442,7 +323,7 @@ static status_t process_start(private_eap_sim_server_t *this,
|
||||
}
|
||||
if (this->use_pseudonym)
|
||||
{
|
||||
permanent = is_pseudonym(this, id);
|
||||
permanent = charon->sim->provider_is_pseudonym(charon->sim, id);
|
||||
if (permanent)
|
||||
{
|
||||
DBG1(DBG_IKE, "received pseudonym identity '%Y' "
|
||||
@@ -477,7 +358,8 @@ static status_t process_start(private_eap_sim_server_t *this,
|
||||
rands.len = kcs.len = sreses.len = 0;
|
||||
for (i = 0; i < TRIPLET_COUNT; i++)
|
||||
{
|
||||
if (!get_triplet(this, this->permanent, rand.ptr, sres.ptr, kc.ptr))
|
||||
if (!charon->sim->provider_get_triplet(charon->sim, this->permanent,
|
||||
rand.ptr, sres.ptr, kc.ptr))
|
||||
{
|
||||
if (this->use_pseudonym)
|
||||
{
|
||||
@@ -514,7 +396,7 @@ static status_t process_start(private_eap_sim_server_t *this,
|
||||
message = simaka_message_create(TRUE, this->identifier++, EAP_SIM,
|
||||
SIM_CHALLENGE, this->crypto);
|
||||
message->add_attribute(message, AT_RAND, rands);
|
||||
id = gen_reauth(this, mk.ptr);
|
||||
id = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk.ptr);
|
||||
if (id)
|
||||
{
|
||||
message->add_attribute(message, AT_NEXT_REAUTH_ID,
|
||||
@@ -523,7 +405,7 @@ static status_t process_start(private_eap_sim_server_t *this,
|
||||
}
|
||||
else
|
||||
{
|
||||
id = gen_pseudonym(this);
|
||||
id = charon->sim->provider_gen_pseudonym(charon->sim, this->permanent);
|
||||
if (id)
|
||||
{
|
||||
message->add_attribute(message, AT_NEXT_PSEUDONYM,
|
||||
|
||||
Reference in New Issue
Block a user