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>
This commit is contained in:
Frederic Leroy 2015-06-10 13:15:24 +02:00 committed by Jouni Malinen
parent a6cc1e5747
commit 7b0f5500b0
7 changed files with 85 additions and 15 deletions

View file

@ -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 */

View file

@ -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:

View file

@ -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;

View file

@ -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;

View file

@ -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 "

View file

@ -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 eloop_register_timeout(data->eap_sim_db_timeout, 0,
* (i.e., last) entry from the list if the limit is reached; could also eap_sim_db_query_timeout, data, entry);
* use timeout to expire pending entries */
} }
@ -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;
} }

View file

@ -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);