summaryrefslogtreecommitdiffstats
path: root/contrib/wpa/src/eap_peer/eap_sim.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/src/eap_peer/eap_sim.c')
-rw-r--r--contrib/wpa/src/eap_peer/eap_sim.c117
1 files changed, 74 insertions, 43 deletions
diff --git a/contrib/wpa/src/eap_peer/eap_sim.c b/contrib/wpa/src/eap_peer/eap_sim.c
index 3d8afb2..c936a44 100644
--- a/contrib/wpa/src/eap_peer/eap_sim.c
+++ b/contrib/wpa/src/eap_peer/eap_sim.c
@@ -1,15 +1,9 @@
/*
* EAP peer method: EAP-SIM (RFC 4186)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -17,6 +11,7 @@
#include "common.h"
#include "pcsc_funcs.h"
#include "crypto/milenage.h"
+#include "crypto/random.h"
#include "eap_peer/eap_i.h"
#include "eap_config.h"
#include "eap_common/eap_sim_common.h"
@@ -93,7 +88,7 @@ static void * eap_sim_init(struct eap_sm *sm)
if (data == NULL)
return NULL;
- if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
+ if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
"for NONCE_MT");
os_free(data);
@@ -122,6 +117,15 @@ static void * eap_sim_init(struct eap_sm *sm)
NULL;
}
+ if (config && config->anonymous_identity) {
+ data->pseudonym = os_malloc(config->anonymous_identity_len);
+ if (data->pseudonym) {
+ os_memcpy(data->pseudonym, config->anonymous_identity,
+ config->anonymous_identity_len);
+ data->pseudonym_len = config->anonymous_identity_len;
+ }
+ }
+
eap_sim_state(data, CONTINUE);
return data;
@@ -263,23 +267,24 @@ static int eap_sim_supported_ver(int version)
#define CLEAR_REAUTH_ID 0x02
#define CLEAR_EAP_ID 0x04
-static void eap_sim_clear_identities(struct eap_sim_data *data, int id)
+static void eap_sim_clear_identities(struct eap_sm *sm,
+ struct eap_sim_data *data, int id)
{
- wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old%s%s%s",
- id & CLEAR_PSEUDONYM ? " pseudonym" : "",
- id & CLEAR_REAUTH_ID ? " reauth_id" : "",
- id & CLEAR_EAP_ID ? " eap_id" : "");
- if (id & CLEAR_PSEUDONYM) {
+ if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
+ wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old pseudonym");
os_free(data->pseudonym);
data->pseudonym = NULL;
data->pseudonym_len = 0;
+ eap_set_anon_id(sm, NULL, 0);
}
- if (id & CLEAR_REAUTH_ID) {
+ if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
+ wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old reauth_id");
os_free(data->reauth_id);
data->reauth_id = NULL;
data->reauth_id_len = 0;
}
- if (id & CLEAR_EAP_ID) {
+ if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
+ wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old eap_id");
os_free(data->last_eap_identity);
data->last_eap_identity = NULL;
data->last_eap_identity_len = 0;
@@ -287,24 +292,45 @@ static void eap_sim_clear_identities(struct eap_sim_data *data, int id)
}
-static int eap_sim_learn_ids(struct eap_sim_data *data,
+static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data,
struct eap_sim_attrs *attr)
{
if (attr->next_pseudonym) {
+ const u8 *identity = NULL;
+ size_t identity_len = 0;
+ const u8 *realm = NULL;
+ size_t realm_len = 0;
+
+ wpa_hexdump_ascii(MSG_DEBUG,
+ "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
+ attr->next_pseudonym,
+ attr->next_pseudonym_len);
os_free(data->pseudonym);
- data->pseudonym = os_malloc(attr->next_pseudonym_len);
+ /* Look for the realm of the permanent identity */
+ identity = eap_get_config_identity(sm, &identity_len);
+ if (identity) {
+ for (realm = identity, realm_len = identity_len;
+ realm_len > 0; realm_len--, realm++) {
+ if (*realm == '@')
+ break;
+ }
+ }
+ data->pseudonym = os_malloc(attr->next_pseudonym_len +
+ realm_len);
if (data->pseudonym == NULL) {
wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
"next pseudonym");
+ data->pseudonym_len = 0;
return -1;
}
os_memcpy(data->pseudonym, attr->next_pseudonym,
attr->next_pseudonym_len);
- data->pseudonym_len = attr->next_pseudonym_len;
- wpa_hexdump_ascii(MSG_DEBUG,
- "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
- data->pseudonym,
- data->pseudonym_len);
+ if (realm_len) {
+ os_memcpy(data->pseudonym + attr->next_pseudonym_len,
+ realm, realm_len);
+ }
+ data->pseudonym_len = attr->next_pseudonym_len + realm_len;
+ eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len);
}
if (attr->next_reauth_id) {
@@ -313,6 +339,7 @@ static int eap_sim_learn_ids(struct eap_sim_data *data,
if (data->reauth_id == NULL) {
wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
"next reauth_id");
+ data->reauth_id_len = 0;
return -1;
}
os_memcpy(data->reauth_id, attr->next_reauth_id,
@@ -337,6 +364,8 @@ static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
data->num_id_req = 0;
data->num_notification = 0;
+ wpa_printf(MSG_DEBUG, "EAP-SIM: Send Client-Error (error code %d)",
+ err);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
EAP_SIM_SUBTYPE_CLIENT_ERROR);
eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
@@ -361,16 +390,16 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
data->pseudonym) {
identity = data->pseudonym;
identity_len = data->pseudonym_len;
- eap_sim_clear_identities(data, CLEAR_REAUTH_ID);
+ eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID);
} else if (id_req != NO_ID_REQ) {
identity = eap_get_config_identity(sm, &identity_len);
if (identity) {
- eap_sim_clear_identities(data, CLEAR_PSEUDONYM |
+ eap_sim_clear_identities(sm, data, CLEAR_PSEUDONYM |
CLEAR_REAUTH_ID);
}
}
if (id_req != NO_ID_REQ)
- eap_sim_clear_identities(data, CLEAR_EAP_ID);
+ eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
@@ -417,7 +446,8 @@ static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data,
static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
- u8 id, int counter_too_small)
+ u8 id, int counter_too_small,
+ const u8 *nonce_s)
{
struct eap_sim_msg *msg;
unsigned int counter;
@@ -452,7 +482,7 @@ static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
}
wpa_printf(MSG_DEBUG, " AT_MAC");
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
- return eap_sim_msg_finish(msg, data->k_aut, data->nonce_s,
+ return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
EAP_SIM_NONCE_S_LEN);
}
@@ -648,11 +678,11 @@ static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
EAP_SIM_UNABLE_TO_PROCESS_PACKET);
}
- /* Old reauthentication and pseudonym identities must not be used
- * anymore. In other words, if no new identities are received, full
- * authentication will be used on next reauthentication. */
- eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
- CLEAR_EAP_ID);
+ /* Old reauthentication identity must not be used anymore. In
+ * other words, if no new reauth identity is received, full
+ * authentication will be used on next reauthentication (using
+ * pseudonym identity or permanent identity). */
+ eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
if (attr->encr_data) {
u8 *decrypted;
@@ -663,7 +693,7 @@ static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
return eap_sim_client_error(
data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET);
}
- eap_sim_learn_ids(data, &eattr);
+ eap_sim_learn_ids(sm, data, &eattr);
os_free(decrypted);
}
@@ -848,7 +878,7 @@ static struct wpabuf * eap_sim_process_reauthentication(
data->reauth_id = NULL;
data->reauth_id_len = 0;
os_free(decrypted);
- return eap_sim_response_reauth(data, id, 1);
+ return eap_sim_response_reauth(data, id, 1, eattr.nonce_s);
}
data->counter = eattr.counter;
@@ -860,8 +890,8 @@ static struct wpabuf * eap_sim_process_reauthentication(
data->reauth_id, data->reauth_id_len,
data->nonce_s, data->mk, data->msk,
data->emsk);
- eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
- eap_sim_learn_ids(data, &eattr);
+ eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
+ eap_sim_learn_ids(sm, data, &eattr);
if (data->result_ind && attr->result_ind)
data->use_result_ind = 1;
@@ -876,10 +906,11 @@ static struct wpabuf * eap_sim_process_reauthentication(
if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) {
wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of "
"fast reauths performed - force fullauth");
- eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
+ eap_sim_clear_identities(sm, data,
+ CLEAR_REAUTH_ID | CLEAR_EAP_ID);
}
os_free(decrypted);
- return eap_sim_response_reauth(data, id, 0);
+ return eap_sim_response_reauth(data, id, 0, data->nonce_s);
}
@@ -987,7 +1018,7 @@ static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv)
static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_sim_data *data = priv;
- eap_sim_clear_identities(data, CLEAR_EAP_ID);
+ eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
data->use_result_ind = 0;
}
@@ -995,7 +1026,7 @@ static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_sim_data *data = priv;
- if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
+ if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
"for NONCE_MT");
os_free(data);
OpenPOWER on IntegriCloud