From 7b0f5500b023deed1acce88cacf3c4606907363f Mon Sep 17 00:00:00 2001 From: Frederic Leroy Date: Wed, 10 Jun 2015 13:15:24 +0200 Subject: [PATCH] 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 --- hostapd/config_file.c | 2 + hostapd/hostapd.conf | 5 +++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/authsrv.c | 1 + src/eap_server/eap_sim_db.c | 88 +++++++++++++++++++++++++++++++------ src/eap_server/eap_sim_db.h | 2 +- 7 files changed, 85 insertions(+), 15 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 2ee46206b..bf424661e 100644 --- a/hostapd/config_file.c +++ b/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) { os_free(bss->eap_sim_db); 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) { bss->eap_sim_aka_result_ind = atoi(pos); #endif /* EAP_SERVER_SIM */ diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index c85681c94..4f51140b5 100644 --- a/hostapd/hostapd.conf +++ b/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 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, # random value. It is configured as a 16-octet value in hex format. It can be # generated, e.g., with the following command: diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 445561c1b..cf9b2ceba 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -65,6 +65,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->dtim_period = 2; bss->radius_server_auth_port = 1812; + bss->eap_sim_db_timeout = 1; bss->ap_max_inactivity = AP_MAX_INACTIVITY; bss->eapol_version = EAPOL_VERSION; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index e66172891..ff9dcb05d 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -239,6 +239,7 @@ struct hostapd_bss_config { struct hostapd_eap_user *eap_user; char *eap_user_sqlite; char *eap_sim_db; + unsigned int eap_sim_db_timeout; int eap_server_erp; /* Whether ERP is enabled on internal EAP server */ struct hostapd_ip_addr own_ip_addr; char *nas_identifier; diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index 934dcfc8d..c9111f6ca 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -193,6 +193,7 @@ int authsrv_init(struct hostapd_data *hapd) if (hapd->conf->eap_sim_db) { hapd->eap_sim_db_priv = eap_sim_db_init(hapd->conf->eap_sim_db, + hapd->conf->eap_sim_db_timeout, hostapd_sim_db_cb, hapd); if (hapd->eap_sim_db_priv == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM " diff --git a/src/eap_server/eap_sim_db.c b/src/eap_server/eap_sim_db.c index acf543530..d84c3d27d 100644 --- a/src/eap_server/eap_sim_db.c +++ b/src/eap_server/eap_sim_db.c @@ -66,6 +66,7 @@ struct eap_sim_db_data { struct eap_sim_pseudonym *pseudonyms; struct eap_sim_reauth *reauths; struct eap_sim_db_pending *pending; + unsigned int eap_sim_db_timeout; #ifdef CONFIG_SQLITE sqlite3 *sqlite_db; 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 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, 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: 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: 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 * @config: Configuration data (e.g., file name) + * @db_timeout: Database lookup timeout * @get_complete_cb: Callback function for reporting availability of triplets * @ctx: Context pointer for get_complete_cb * Returns: Pointer to a private data structure or %NULL on failure */ 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 *ctx) { @@ -709,6 +766,7 @@ eap_sim_db_init(const char *config, data->sock = -1; data->get_complete_cb = get_complete_cb; data->ctx = ctx; + data->eap_sim_db_timeout = db_timeout; data->fname = os_strdup(config); if (data->fname == NULL) goto fail; @@ -796,7 +854,7 @@ void eap_sim_db_deinit(void *priv) while (pending) { prev_pending = pending; pending = pending->next; - os_free(prev_pending); + eap_sim_db_free_pending(data, prev_pending); } 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) { wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> " "failure"); - os_free(entry); + eap_sim_db_free_pending(data, entry); 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, num_chal * EAP_SIM_SRES_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; } @@ -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->state = PENDING; 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; } @@ -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); if (entry) { if (entry->state == FAILURE) { - os_free(entry); + eap_sim_db_free_pending(data, entry); wpa_printf(MSG_DEBUG, "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(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN); *res_len = entry->u.aka.res_len; - os_free(entry); + eap_sim_db_free_pending(data, entry); 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->state = PENDING; 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; } diff --git a/src/eap_server/eap_sim_db.h b/src/eap_server/eap_sim_db.h index 53a1a7c3b..ca900b915 100644 --- a/src/eap_server/eap_sim_db.h +++ b/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 * -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 *ctx);