From: Martin Willi Date: Tue, 27 Oct 2009 10:12:36 +0000 (+0100) Subject: Fallback to permanent identity request if pseudonym mapping failed X-Git-Tag: 4.3.6~223 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e1a8729de0ebe5e1f7ac14b3b852f9b7142ae582;p=thirdparty%2Fstrongswan.git Fallback to permanent identity request if pseudonym mapping failed --- diff --git a/src/charon/plugins/eap_sim/eap_sim_peer.c b/src/charon/plugins/eap_sim/eap_sim_peer.c index b9b2aa4c6e..8c1cece47d 100644 --- a/src/charon/plugins/eap_sim/eap_sim_peer.c +++ b/src/charon/plugins/eap_sim/eap_sim_peer.c @@ -188,6 +188,10 @@ static status_t process_start(private_eap_sim_peer_t *this, bool supported = FALSE; simaka_attribute_t id_req = 0; + /* if this is the second invocation, server did not accept our pseudonym */ + DESTROY_IF(this->pseudonym); + this->pseudonym = NULL; + enumerator = in->create_attribute_enumerator(in); while (enumerator->enumerate(enumerator, &type, &data)) { @@ -238,7 +242,6 @@ static status_t process_start(private_eap_sim_peer_t *this, case AT_ANY_ID_REQ: /* TODO: reauth handling */ case AT_FULLAUTH_ID_REQ: - DESTROY_IF(this->pseudonym); this->pseudonym = get_pseudonym(this); if (this->pseudonym) { @@ -312,12 +315,6 @@ static status_t process_challenge(private_eap_sim_peer_t *this, } enumerator->destroy(enumerator); - peer = this->permanent; - if (this->pseudonym) - { - peer = this->pseudonym; - } - /* excepting two or three RAND, each 16 bytes. We require two valid * and different RANDs */ if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) || @@ -333,7 +330,7 @@ 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, peer, rands.ptr, sres.ptr, kc.ptr)) + if (!get_triplet(this, 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), @@ -347,6 +344,11 @@ static status_t process_challenge(private_eap_sim_peer_t *this, rands = chunk_skip(rands, SIM_RAND_LEN); } + peer = this->permanent; + if (this->pseudonym) + { + peer = this->pseudonym; + } data = chunk_cata("cccc", kcs, this->nonce, this->version_list, version); free(this->msk.ptr); this->msk = this->crypto->derive_keys_full(this->crypto, peer, data); diff --git a/src/charon/plugins/eap_sim/eap_sim_server.c b/src/charon/plugins/eap_sim/eap_sim_server.c index 3ecbdfe0ba..dc4f0fb168 100644 --- a/src/charon/plugins/eap_sim/eap_sim_server.c +++ b/src/charon/plugins/eap_sim/eap_sim_server.c @@ -40,6 +40,11 @@ struct private_eap_sim_server_t { */ identification_t *permanent; + /** + * pseudonym ID of peer + */ + identification_t *pseudonym; + /** * EAP-SIM/AKA crypto helper */ @@ -132,6 +137,58 @@ static identification_t* gen_pseudonym(private_eap_sim_server_t *this) 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 + */ +static status_t initiate(private_eap_sim_server_t *this, eap_payload_t **out) +{ + simaka_message_t *message; + + message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, + SIM_START, this->crypto); + message->add_attribute(message, AT_VERSION_LIST, version); + if (this->use_reauth) + { + message->add_attribute(message, AT_ANY_ID_REQ, chunk_empty); + } + else if (this->use_pseudonym) + { + message->add_attribute(message, AT_FULLAUTH_ID_REQ, chunk_empty); + } + else if (this->use_permanent) + { + message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty); + } + *out = message->generate(message, chunk_empty); + message->destroy(message); + + this->pending = SIM_START; + return NEED_MORE; +} + /** * process an EAP-SIM/Response/Start message */ @@ -141,10 +198,10 @@ static status_t process_start(private_eap_sim_server_t *this, simaka_message_t *message; enumerator_t *enumerator; simaka_attribute_t type; - chunk_t data, id = chunk_empty, nonce = chunk_empty; + chunk_t data, identity = chunk_empty, nonce = chunk_empty; chunk_t rands, rand, kcs, kc, sreses, sres; bool supported = FALSE; - identification_t *peer = NULL, *pseudonym; + identification_t *id; int i; if (this->pending != SIM_START) @@ -169,7 +226,7 @@ static status_t process_start(private_eap_sim_server_t *this, } break; case AT_IDENTITY: - id = data; + identity = data; break; default: if (!simaka_attribute_skippable(type)) @@ -188,24 +245,35 @@ static status_t process_start(private_eap_sim_server_t *this, return FAILED; } - if (id.len) + if (identity.len) { - if (this->use_reauth) + char buf[identity.len + 1]; + + snprintf(buf, sizeof(buf), "%.*s", identity.len, identity.ptr); + id = identification_create_from_string(buf); + + if (this->use_pseudonym) { - /* TODO: handle reauthentication identity */ + identification_t *permanent; + + permanent = is_pseudonym(this, id); + if (permanent) + { + DBG1(DBG_IKE, "received pseudonym identity '%Y' mapping to '%Y'", + id, permanent); + this->permanent->destroy(this->permanent); + this->permanent = permanent; + this->pseudonym = id->clone(id); + } } - if (this->use_pseudonym || this->use_permanent) + if (!this->pseudonym && this->use_permanent) { - char buf[id.len + 1]; - - snprintf(buf, sizeof(buf), "%.*s", id.len, id.ptr); - peer = identification_create_from_string(buf); - DBG1(DBG_CFG, "received (pseudonym) identity '%Y'", peer); + DBG1(DBG_IKE, "received %spermanent identity '%Y'", + this->use_pseudonym ? "pseudonym or " : "", id); + this->permanent->destroy(this->permanent); + this->permanent = id->clone(id); } - } - if (!peer) - { - peer = this->permanent->clone(this->permanent); + id->destroy(id); } /* read triplets from provider */ @@ -215,9 +283,18 @@ 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, peer, rand.ptr, sres.ptr, kc.ptr)) + if (!get_triplet(this, this->permanent, rand.ptr, sres.ptr, kc.ptr)) { - peer->destroy(peer); + if (this->use_pseudonym) + { + /* probably received a pseudonym we couldn't map */ + DBG1(DBG_IKE, "failed to map pseudonym identity '%Y', " + "fallback to fullauth identity request", this->permanent); + this->use_pseudonym = FALSE; + DESTROY_IF(this->pseudonym); + this->pseudonym = NULL; + return initiate(this, out); + } return FAILED; } rands.len += SIM_RAND_LEN; @@ -232,8 +309,12 @@ static status_t process_start(private_eap_sim_server_t *this, data = chunk_cata("cccc", kcs, nonce, version, version); free(this->msk.ptr); - this->msk = this->crypto->derive_keys_full(this->crypto, peer, data); - peer->destroy(peer); + id = this->permanent; + if (this->pseudonym) + { + id = this->pseudonym; + } + this->msk = this->crypto->derive_keys_full(this->crypto, id, data); /* build response with AT_MAC, built over "EAP packet | NONCE_MT" */ message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, @@ -242,13 +323,13 @@ static status_t process_start(private_eap_sim_server_t *this, if (this->use_pseudonym) { /* generate new pseudonym for next authentication */ - pseudonym = gen_pseudonym(this); - if (peer) + id = gen_pseudonym(this); + if (id) { - DBG1(DBG_IKE, "proposing new pseudonym '%Y'", pseudonym); + DBG1(DBG_IKE, "proposing new pseudonym '%Y'", id); message->add_attribute(message, AT_NEXT_PSEUDONYM, - pseudonym->get_encoding(pseudonym)); - pseudonym->destroy(pseudonym); + id->get_encoding(id)); + id->destroy(id); } } *out = message->generate(message, nonce); @@ -365,35 +446,6 @@ static status_t process(private_eap_sim_server_t *this, return status; } -/** - * Implementation of eap_method_t.initiate - */ -static status_t initiate(private_eap_sim_server_t *this, eap_payload_t **out) -{ - simaka_message_t *message; - - message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, - SIM_START, this->crypto); - message->add_attribute(message, AT_VERSION_LIST, version); - if (this->use_reauth) - { - message->add_attribute(message, AT_ANY_ID_REQ, chunk_empty); - } - else if (this->use_pseudonym) - { - message->add_attribute(message, AT_FULLAUTH_ID_REQ, chunk_empty); - } - else if (this->use_permanent) - { - message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty); - } - *out = message->generate(message, chunk_empty); - message->destroy(message); - - this->pending = SIM_START; - return NEED_MORE; -} - /** * Implementation of eap_method_t.get_type. */ @@ -431,6 +483,7 @@ static void destroy(private_eap_sim_server_t *this) { this->crypto->destroy(this->crypto); this->permanent->destroy(this->permanent); + DESTROY_IF(this->pseudonym); free(this->sreses.ptr); free(this->msk.ptr); free(this); @@ -458,11 +511,12 @@ eap_sim_server_t *eap_sim_server_create(identification_t *server, return NULL; } this->permanent = peer->clone(peer); + this->pseudonym = NULL; this->sreses = chunk_empty; this->msk = chunk_empty; this->pending = 0; this->use_reauth = lib->settings->get_bool(lib->settings, - "charon.plugins.eap-sim.use_reauth", TRUE); + "charon.plugins.eap-sim.use_reauth", FALSE); this->use_pseudonym = lib->settings->get_bool(lib->settings, "charon.plugins.eap-sim.use_pseudonym", TRUE); this->use_permanent = lib->settings->get_bool(lib->settings,