Parcourir la source

EAP-AKA server: Store permanent username in session data

This allows identity use to be cleaned up in various operations.

Signed-hostap: Jouni Malinen <j@w1.fi>
Jouni Malinen il y a 12 ans
Parent
commit
8a9f58f2cc
1 fichiers modifiés avec 111 ajouts et 126 suppressions
  1. 111 126
      src/eap_server/eap_server_aka.c

+ 111 - 126
src/eap_server/eap_server_aka.c

@@ -50,14 +50,10 @@ struct eap_aka_data {
 	size_t network_name_len;
 	u16 kdf;
 	int identity_round;
+	char permanent[20]; /* Permanent username */
 };
 
 
-static void eap_aka_determine_identity(struct eap_sm *sm,
-				       struct eap_aka_data *data,
-				       int before_identity, int after_reauth);
-
-
 static const char * eap_aka_state_txt(int state)
 {
 	switch (state) {
@@ -104,7 +100,6 @@ static void * eap_aka_init(struct eap_sm *sm)
 	data->eap_method = EAP_TYPE_AKA;
 
 	data->state = IDENTITY;
-	eap_aka_determine_identity(sm, data, 1, 0);
 	data->pending_id = -1;
 
 	return data;
@@ -137,7 +132,6 @@ static void * eap_aka_prime_init(struct eap_sm *sm)
 	data->network_name_len = os_strlen(network_name);
 
 	data->state = IDENTITY;
-	eap_aka_determine_identity(sm, data, 1, 0);
 	data->pending_id = -1;
 
 	return data;
@@ -621,105 +615,121 @@ static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
 }
 
 
-static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data,
-			     const u8 *identity, size_t identity_len);
+static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
 
 static void eap_aka_determine_identity(struct eap_sm *sm,
-				       struct eap_aka_data *data,
-				       int before_identity, int after_reauth)
+				       struct eap_aka_data *data)
 {
-	const u8 *identity;
-	size_t identity_len;
+	char *username;
 
-	identity = NULL;
-	identity_len = 0;
+	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
+			  sm->identity, sm->identity_len);
 
-	if (after_reauth && data->reauth) {
-		identity = data->reauth->identity;
-		identity_len = data->reauth->identity_len;
-	} else if (sm->identity && sm->identity_len > 0 &&
-		   (sm->identity[0] == EAP_AKA_PERMANENT_PREFIX ||
-		    sm->identity[0] == EAP_AKA_PRIME_PERMANENT_PREFIX)) {
-		identity = sm->identity;
-		identity_len = sm->identity_len;
-	} else {
-		identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
-						    sm->identity,
-						    sm->identity_len,
-						    &identity_len);
-		if (identity == NULL) {
-			data->reauth = eap_sim_db_get_reauth_entry(
-				sm->eap_sim_db_priv, sm->identity,
-				sm->identity_len);
-			if (data->reauth &&
-			    (data->reauth->reauth_id[0] ==
-			     EAP_AKA_PRIME_REAUTH_ID_PREFIX) !=
-			    (data->eap_method == EAP_TYPE_AKA_PRIME)) {
-				wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data "
-					   "was for different AKA version");
-				data->reauth = NULL;
-			}
-			if (data->reauth) {
-				wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast "
-					   "re-authentication");
-				identity = data->reauth->identity;
-				identity_len = data->reauth->identity_len;
-				data->counter = data->reauth->counter;
-				if (data->eap_method == EAP_TYPE_AKA_PRIME) {
-					os_memcpy(data->k_encr,
-						  data->reauth->k_encr,
-						  EAP_SIM_K_ENCR_LEN);
-					os_memcpy(data->k_aut,
-						  data->reauth->k_aut,
-						  EAP_AKA_PRIME_K_AUT_LEN);
-					os_memcpy(data->k_re,
-						  data->reauth->k_re,
-						  EAP_AKA_PRIME_K_RE_LEN);
-				} else {
-					os_memcpy(data->mk, data->reauth->mk,
-						  EAP_SIM_MK_LEN);
-				}
-			}
-		}
+	username = sim_get_username(sm->identity, sm->identity_len);
+	if (username == NULL) {
+		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
+		eap_aka_state(data, NOTIFICATION);
+		return;
 	}
 
-	if (identity == NULL ||
-	    eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
-				      sm->identity_len) < 0) {
-		if (before_identity) {
-			wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name "
-				   "not known - send AKA-Identity request");
-			eap_aka_state(data, IDENTITY);
+	if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
+	     username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) ||
+	    (data->eap_method == EAP_TYPE_AKA &&
+	     username[0] == EAP_AKA_REAUTH_ID_PREFIX)) {
+		size_t len;
+		wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'",
+			   username);
+		data->reauth = eap_sim_db_get_reauth_entry(
+			sm->eap_sim_db_priv, sm->identity,
+			sm->identity_len);
+		os_free(username);
+		if (data->reauth &&
+		    (data->reauth->reauth_id[0] ==
+		     EAP_AKA_PRIME_REAUTH_ID_PREFIX) !=
+		    (data->eap_method == EAP_TYPE_AKA_PRIME)) {
+			wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data "
+				   "was for different AKA version");
+			data->reauth = NULL;
+		}
+		if (data->reauth == NULL) {
+			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth "
+				   "identity - request full auth identity");
+			/* Remain in IDENTITY state for another round */
 			return;
+		}
+		wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication");
+		len = data->reauth->identity_len;
+		if (len >= sizeof(data->permanent))
+			len = sizeof(data->permanent) - 1;
+		os_memcpy(data->permanent, data->reauth->identity, len);
+		data->permanent[len] = '\0';
+		data->counter = data->reauth->counter;
+		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
+			os_memcpy(data->k_encr, data->reauth->k_encr,
+				  EAP_SIM_K_ENCR_LEN);
+			os_memcpy(data->k_aut, data->reauth->k_aut,
+				  EAP_AKA_PRIME_K_AUT_LEN);
+			os_memcpy(data->k_re, data->reauth->k_re,
+				  EAP_AKA_PRIME_K_RE_LEN);
 		} else {
-			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the "
-				   "permanent user name is known; try to use "
-				   "it");
-			/* eap_sim_db_get_aka_auth() will report failure, if
-			 * this identity is not known. */
+			os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
 		}
-	}
-
-	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
-			  identity, identity_len);
-
-	if (!after_reauth && data->reauth) {
 		eap_aka_state(data, REAUTH);
 		return;
 	}
 
+	if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
+	     username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
+	    (data->eap_method == EAP_TYPE_AKA &&
+	     username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
+		const u8 *permanent;
+		size_t len;
+		wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
+			   username);
+		permanent = eap_sim_db_get_permanent(
+			sm->eap_sim_db_priv, (u8 *) username,
+			os_strlen(username), &len);
+		os_free(username);
+		if (permanent == NULL) {
+			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
+				   "identity - request permanent identity");
+			/* Remain in IDENTITY state for another round */
+			return;
+		}
+		if (len >= sizeof(data->permanent))
+			len = sizeof(data->permanent) - 1;
+		os_memcpy(data->permanent, permanent, len);
+		data->permanent[len] = '\0';
+	} else if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
+		    username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) ||
+		   (data->eap_method == EAP_TYPE_AKA &&
+		    username[0] == EAP_AKA_PERMANENT_PREFIX)) {
+		wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'",
+			   username);
+		os_strlcpy(data->permanent, username, sizeof(data->permanent));
+		os_free(username);
+	} else {
+		wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
+			   username);
+		os_free(username);
+		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
+		eap_aka_state(data, NOTIFICATION);
+		return;
+	}
 
-	eap_aka_fullauth(sm, data, identity, identity_len);
+	eap_aka_fullauth(sm, data);
 }
 
 
-static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data,
-			     const u8 *identity, size_t identity_len)
+static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data)
 {
+	size_t identity_len;
 	int res;
 
-	res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity,
-				      identity_len, data->rand, data->autn,
+	res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv,
+				      (u8 *) data->permanent,
+				      os_strlen(data->permanent),
+				      data->rand, data->autn,
 				      data->ik, data->ck, data->res,
 				      &data->res_len, sm);
 	if (res == EAP_SIM_DB_PENDING) {
@@ -820,7 +830,7 @@ static void eap_aka_process_identity(struct eap_sm *sm,
 	os_memcpy(sm->identity, attr->identity, attr->identity_len);
 	sm->identity_len = attr->identity_len;
 
-	eap_aka_determine_identity(sm, data, 0, 0);
+	eap_aka_determine_identity(sm, data);
 	if (eap_get_id(respData) == data->pending_id) {
 		data->pending_id = -1;
 		eap_aka_add_id_msg(data, respData);
@@ -845,9 +855,6 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
 				      struct wpabuf *respData,
 				      struct eap_sim_attrs *attr)
 {
-	const u8 *identity;
-	size_t identity_len;
-
 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
 
 #ifdef EAP_SERVER_AKA_PRIME
@@ -920,16 +927,10 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
 	} else
 		eap_aka_state(data, SUCCESS);
 
-	identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
-					    sm->identity_len, &identity_len);
-	if (identity == NULL) {
-		identity = sm->identity;
-		identity_len = sm->identity_len;
-	}
-
 	if (data->next_pseudonym) {
-		eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
-					 identity_len,
+		eap_sim_db_add_pseudonym(sm->eap_sim_db_priv,
+					 (u8 *) data->permanent,
+					 os_strlen(data->permanent),
 					 data->next_pseudonym);
 		data->next_pseudonym = NULL;
 	}
@@ -937,16 +938,17 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
 #ifdef EAP_SERVER_AKA_PRIME
 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
-						    identity,
-						    identity_len,
+						    (u8 *) data->permanent,
+						    os_strlen(data->permanent),
 						    data->next_reauth_id,
 						    data->counter + 1,
 						    data->k_encr, data->k_aut,
 						    data->k_re);
 #endif /* EAP_SERVER_AKA_PRIME */
 		} else {
-			eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
-					      identity_len,
+			eap_sim_db_add_reauth(sm->eap_sim_db_priv,
+					      (u8 *) data->permanent,
+					      os_strlen(data->permanent),
 					      data->next_reauth_id,
 					      data->counter + 1,
 					      data->mk);
@@ -985,8 +987,7 @@ static void eap_aka_process_sync_failure(struct eap_sm *sm,
 	}
 	data->auts_reported = 1;
 
-	/* Try again after resynchronization */
-	eap_aka_determine_identity(sm, data, 0, 0);
+	/* Remain in CHALLENGE state to re-try after resynchronization */
 }
 
 
@@ -997,8 +998,6 @@ static void eap_aka_process_reauth(struct eap_sm *sm,
 {
 	struct eap_sim_attrs eattr;
 	u8 *decrypted = NULL;
-	const u8 *identity, *id2;
-	size_t identity_len, id2_len;
 
 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
 
@@ -1041,7 +1040,7 @@ static void eap_aka_process_reauth(struct eap_sm *sm,
 		wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
 			   "included AT_COUNTER_TOO_SMALL - starting full "
 			   "authentication");
-		eap_aka_determine_identity(sm, data, 0, 1);
+		eap_aka_fullauth(sm, data);
 		return;
 	}
 
@@ -1052,35 +1051,21 @@ static void eap_aka_process_reauth(struct eap_sm *sm,
 	} else
 		eap_aka_state(data, SUCCESS);
 
-	if (data->reauth) {
-		identity = data->reauth->identity;
-		identity_len = data->reauth->identity_len;
-	} else {
-		identity = sm->identity;
-		identity_len = sm->identity_len;
-	}
-
-	id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
-				       identity_len, &id2_len);
-	if (id2) {
-		identity = id2;
-		identity_len = id2_len;
-	}
-
 	if (data->next_reauth_id) {
 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
 #ifdef EAP_SERVER_AKA_PRIME
 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
-						    identity,
-						    identity_len,
+						    (u8 *) data->permanent,
+						    os_strlen(data->permanent),
 						    data->next_reauth_id,
 						    data->counter + 1,
 						    data->k_encr, data->k_aut,
 						    data->k_re);
 #endif /* EAP_SERVER_AKA_PRIME */
 		} else {
-			eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
-					      identity_len,
+			eap_sim_db_add_reauth(sm->eap_sim_db_priv,
+					      (u8 *) data->permanent,
+					      os_strlen(data->permanent),
 					      data->next_reauth_id,
 					      data->counter + 1,
 					      data->mk);