Browse Source

eap_sim_db: Implement eap_sim_db_expire_pending()

Expire pending DB request for EAP-SIM/AKA/AKA'. Timeout defaults to 1
second and is user configurable in hostapd.conf (eap_sim_db_timeout).

Signed-off-by: Frederic Leroy <frederic.leroy@b-com.com>
Frederic Leroy 9 years ago
parent
commit
7b0f5500b0

+ 2 - 0
hostapd/config_file.c

@@ -2187,6 +2187,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 	} else if (os_strcmp(buf, "eap_sim_db") == 0) {
 	} else if (os_strcmp(buf, "eap_sim_db") == 0) {
 		os_free(bss->eap_sim_db);
 		os_free(bss->eap_sim_db);
 		bss->eap_sim_db = os_strdup(pos);
 		bss->eap_sim_db = os_strdup(pos);
+	} else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) {
+		bss->eap_sim_db_timeout = atoi(pos);
 	} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
 	} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
 		bss->eap_sim_aka_result_ind = atoi(pos);
 		bss->eap_sim_aka_result_ind = atoi(pos);
 #endif /* EAP_SERVER_SIM */
 #endif /* EAP_SERVER_SIM */

+ 5 - 0
hostapd/hostapd.conf

@@ -832,6 +832,11 @@ eap_server=0
 #eap_sim_db=unix:/tmp/hlr_auc_gw.sock
 #eap_sim_db=unix:/tmp/hlr_auc_gw.sock
 #eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db
 #eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db
 
 
+# EAP-SIM DB request timeout
+# This parameter sets the maximum time to wait for a database request response.
+# The parameter value is in seconds.
+#eap_sim_db_timeout=1
+
 # Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,
 # Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,
 # random value. It is configured as a 16-octet value in hex format. It can be
 # random value. It is configured as a 16-octet value in hex format. It can be
 # generated, e.g., with the following command:
 # generated, e.g., with the following command:

+ 1 - 0
src/ap/ap_config.c

@@ -65,6 +65,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 	bss->dtim_period = 2;
 	bss->dtim_period = 2;
 
 
 	bss->radius_server_auth_port = 1812;
 	bss->radius_server_auth_port = 1812;
+	bss->eap_sim_db_timeout = 1;
 	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
 	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
 	bss->eapol_version = EAPOL_VERSION;
 	bss->eapol_version = EAPOL_VERSION;
 
 

+ 1 - 0
src/ap/ap_config.h

@@ -239,6 +239,7 @@ struct hostapd_bss_config {
 	struct hostapd_eap_user *eap_user;
 	struct hostapd_eap_user *eap_user;
 	char *eap_user_sqlite;
 	char *eap_user_sqlite;
 	char *eap_sim_db;
 	char *eap_sim_db;
+	unsigned int eap_sim_db_timeout;
 	int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
 	int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
 	struct hostapd_ip_addr own_ip_addr;
 	struct hostapd_ip_addr own_ip_addr;
 	char *nas_identifier;
 	char *nas_identifier;

+ 1 - 0
src/ap/authsrv.c

@@ -193,6 +193,7 @@ int authsrv_init(struct hostapd_data *hapd)
 	if (hapd->conf->eap_sim_db) {
 	if (hapd->conf->eap_sim_db) {
 		hapd->eap_sim_db_priv =
 		hapd->eap_sim_db_priv =
 			eap_sim_db_init(hapd->conf->eap_sim_db,
 			eap_sim_db_init(hapd->conf->eap_sim_db,
+					hapd->conf->eap_sim_db_timeout,
 					hostapd_sim_db_cb, hapd);
 					hostapd_sim_db_cb, hapd);
 		if (hapd->eap_sim_db_priv == NULL) {
 		if (hapd->eap_sim_db_priv == NULL) {
 			wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
 			wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "

+ 74 - 14
src/eap_server/eap_sim_db.c

@@ -66,6 +66,7 @@ struct eap_sim_db_data {
 	struct eap_sim_pseudonym *pseudonyms;
 	struct eap_sim_pseudonym *pseudonyms;
 	struct eap_sim_reauth *reauths;
 	struct eap_sim_reauth *reauths;
 	struct eap_sim_db_pending *pending;
 	struct eap_sim_db_pending *pending;
+	unsigned int eap_sim_db_timeout;
 #ifdef CONFIG_SQLITE
 #ifdef CONFIG_SQLITE
 	sqlite3 *sqlite_db;
 	sqlite3 *sqlite_db;
 	char db_tmp_identity[100];
 	char db_tmp_identity[100];
@@ -76,6 +77,10 @@ struct eap_sim_db_data {
 };
 };
 
 
 
 
+static void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx);
+static void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx);
+
+
 #ifdef CONFIG_SQLITE
 #ifdef CONFIG_SQLITE
 
 
 static int db_table_exists(sqlite3 *db, const char *name)
 static int db_table_exists(sqlite3 *db, const char *name)
@@ -397,6 +402,57 @@ static void eap_sim_db_add_pending(struct eap_sim_db_data *data,
 }
 }
 
 
 
 
+static void eap_sim_db_free_pending(struct eap_sim_db_data *data,
+				    struct eap_sim_db_pending *entry)
+{
+	eloop_cancel_timeout(eap_sim_db_query_timeout, data, entry);
+	eloop_cancel_timeout(eap_sim_db_del_timeout, data, entry);
+	os_free(entry);
+}
+
+
+static void eap_sim_db_del_pending(struct eap_sim_db_data *data,
+				   struct eap_sim_db_pending *entry)
+{
+	struct eap_sim_db_pending **pp = &data->pending;
+
+	while (*pp != NULL) {
+		if (*pp == entry) {
+			*pp = entry->next;
+			eap_sim_db_free_pending(data, entry);
+			return;
+		}
+		pp = &(*pp)->next;
+	}
+}
+
+
+static void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx)
+{
+	struct eap_sim_db_data *data = eloop_ctx;
+	struct eap_sim_db_pending *entry = user_ctx;
+
+	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Delete query timeout for %p", entry);
+	eap_sim_db_del_pending(data, entry);
+}
+
+
+static void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx)
+{
+	struct eap_sim_db_data *data = eloop_ctx;
+	struct eap_sim_db_pending *entry = user_ctx;
+
+	/*
+	 * Report failure and allow some time for EAP server to process it
+	 * before deleting the query.
+	 */
+	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Query timeout for %p", entry);
+	entry->state = FAILURE;
+	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
+	eloop_register_timeout(1, 0, eap_sim_db_del_timeout, data, entry);
+}
+
+
 static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
 static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
 				     const char *imsi, char *buf)
 				     const char *imsi, char *buf)
 {
 {
@@ -472,7 +528,7 @@ static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
 
 
 parse_fail:
 parse_fail:
 	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
 	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
-	os_free(entry);
+	eap_sim_db_free_pending(data, entry);
 }
 }
 
 
 
 
@@ -563,7 +619,7 @@ static void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data,
 
 
 parse_fail:
 parse_fail:
 	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
 	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
-	os_free(entry);
+	eap_sim_db_free_pending(data, entry);
 }
 }
 
 
 
 
@@ -690,12 +746,13 @@ static void eap_sim_db_close_socket(struct eap_sim_db_data *data)
 /**
 /**
  * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
  * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
  * @config: Configuration data (e.g., file name)
  * @config: Configuration data (e.g., file name)
+ * @db_timeout: Database lookup timeout
  * @get_complete_cb: Callback function for reporting availability of triplets
  * @get_complete_cb: Callback function for reporting availability of triplets
  * @ctx: Context pointer for get_complete_cb
  * @ctx: Context pointer for get_complete_cb
  * Returns: Pointer to a private data structure or %NULL on failure
  * Returns: Pointer to a private data structure or %NULL on failure
  */
  */
 struct eap_sim_db_data *
 struct eap_sim_db_data *
-eap_sim_db_init(const char *config,
+eap_sim_db_init(const char *config, unsigned int db_timeout,
 		void (*get_complete_cb)(void *ctx, void *session_ctx),
 		void (*get_complete_cb)(void *ctx, void *session_ctx),
 		void *ctx)
 		void *ctx)
 {
 {
@@ -709,6 +766,7 @@ eap_sim_db_init(const char *config,
 	data->sock = -1;
 	data->sock = -1;
 	data->get_complete_cb = get_complete_cb;
 	data->get_complete_cb = get_complete_cb;
 	data->ctx = ctx;
 	data->ctx = ctx;
+	data->eap_sim_db_timeout = db_timeout;
 	data->fname = os_strdup(config);
 	data->fname = os_strdup(config);
 	if (data->fname == NULL)
 	if (data->fname == NULL)
 		goto fail;
 		goto fail;
@@ -796,7 +854,7 @@ void eap_sim_db_deinit(void *priv)
 	while (pending) {
 	while (pending) {
 		prev_pending = pending;
 		prev_pending = pending;
 		pending = pending->next;
 		pending = pending->next;
-		os_free(prev_pending);
+		eap_sim_db_free_pending(data, prev_pending);
 	}
 	}
 
 
 	os_free(data);
 	os_free(data);
@@ -833,11 +891,11 @@ static int eap_sim_db_send(struct eap_sim_db_data *data, const char *msg,
 }
 }
 
 
 
 
-static void eap_sim_db_expire_pending(struct eap_sim_db_data *data)
+static void eap_sim_db_expire_pending(struct eap_sim_db_data *data,
+				      struct eap_sim_db_pending *entry)
 {
 {
-	/* TODO: add limit for maximum length for pending list; remove latest
-	 * (i.e., last) entry from the list if the limit is reached; could also
-	 * use timeout to expire pending entries */
+	eloop_register_timeout(data->eap_sim_db_timeout, 0,
+			       eap_sim_db_query_timeout, data, entry);
 }
 }
 
 
 
 
@@ -891,7 +949,7 @@ int eap_sim_db_get_gsm_triplets(struct eap_sim_db_data *data,
 		if (entry->state == FAILURE) {
 		if (entry->state == FAILURE) {
 			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
 			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
 				   "failure");
 				   "failure");
-			os_free(entry);
+			eap_sim_db_free_pending(data, entry);
 			return EAP_SIM_DB_FAILURE;
 			return EAP_SIM_DB_FAILURE;
 		}
 		}
 
 
@@ -911,7 +969,7 @@ int eap_sim_db_get_gsm_triplets(struct eap_sim_db_data *data,
 		os_memcpy(sres, entry->u.sim.sres,
 		os_memcpy(sres, entry->u.sim.sres,
 			  num_chal * EAP_SIM_SRES_LEN);
 			  num_chal * EAP_SIM_SRES_LEN);
 		os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
 		os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
-		os_free(entry);
+		eap_sim_db_free_pending(data, entry);
 		return num_chal;
 		return num_chal;
 	}
 	}
 
 
@@ -945,7 +1003,8 @@ int eap_sim_db_get_gsm_triplets(struct eap_sim_db_data *data,
 	entry->cb_session_ctx = cb_session_ctx;
 	entry->cb_session_ctx = cb_session_ctx;
 	entry->state = PENDING;
 	entry->state = PENDING;
 	eap_sim_db_add_pending(data, entry);
 	eap_sim_db_add_pending(data, entry);
-	eap_sim_db_expire_pending(data);
+	eap_sim_db_expire_pending(data, entry);
+	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
 
 
 	return EAP_SIM_DB_PENDING;
 	return EAP_SIM_DB_PENDING;
 }
 }
@@ -1356,7 +1415,7 @@ int eap_sim_db_get_aka_auth(struct eap_sim_db_data *data, const char *username,
 	entry = eap_sim_db_get_pending(data, imsi, 1);
 	entry = eap_sim_db_get_pending(data, imsi, 1);
 	if (entry) {
 	if (entry) {
 		if (entry->state == FAILURE) {
 		if (entry->state == FAILURE) {
-			os_free(entry);
+			eap_sim_db_free_pending(data, entry);
 			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
 			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
 			return EAP_SIM_DB_FAILURE;
 			return EAP_SIM_DB_FAILURE;
 		}
 		}
@@ -1375,7 +1434,7 @@ int eap_sim_db_get_aka_auth(struct eap_sim_db_data *data, const char *username,
 		os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
 		os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
 		os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
 		os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
 		*res_len = entry->u.aka.res_len;
 		*res_len = entry->u.aka.res_len;
-		os_free(entry);
+		eap_sim_db_free_pending(data, entry);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1406,7 +1465,8 @@ int eap_sim_db_get_aka_auth(struct eap_sim_db_data *data, const char *username,
 	entry->cb_session_ctx = cb_session_ctx;
 	entry->cb_session_ctx = cb_session_ctx;
 	entry->state = PENDING;
 	entry->state = PENDING;
 	eap_sim_db_add_pending(data, entry);
 	eap_sim_db_add_pending(data, entry);
-	eap_sim_db_expire_pending(data);
+	eap_sim_db_expire_pending(data, entry);
+	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
 
 
 	return EAP_SIM_DB_PENDING;
 	return EAP_SIM_DB_PENDING;
 }
 }

+ 1 - 1
src/eap_server/eap_sim_db.h

@@ -31,7 +31,7 @@ enum eap_sim_db_method {
 struct eap_sim_db_data;
 struct eap_sim_db_data;
 
 
 struct eap_sim_db_data *
 struct eap_sim_db_data *
-eap_sim_db_init(const char *config,
+eap_sim_db_init(const char *config, unsigned int db_timeout,
 		void (*get_complete_cb)(void *ctx, void *session_ctx),
 		void (*get_complete_cb)(void *ctx, void *session_ctx),
 		void *ctx);
 		void *ctx);