18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-SIM database/authenticator gateway
304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2005-2010, 2012, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is an example implementation of the EAP-SIM/AKA database/authentication
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * gateway interface that is using an external program as an SS7 gateway to
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GSM/UMTS authentication center (HLR/AuC). hlr_auc_gw is an example
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * implementation of such a gateway program. This eap_sim_db.c takes care of
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM/AKA pseudonyms and re-auth identities. It can be used with different
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * gateway implementations for HLR/AuC access. Alternatively, it can also be
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * completely replaced if the in-memory database of pseudonyms/re-auth
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identities is not suitable for some cases.
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/un.h>
204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#include <sqlite3.h>
224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_sim_common.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_sim_db.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_pseudonym {
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *next;
324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *permanent; /* permanent username */
334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *pseudonym; /* pseudonym username */
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_db_pending {
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *next;
384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char imsi[20];
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { PENDING, SUCCESS, FAILURE } state;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *cb_session_ctx;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int aka;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union {
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct {
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN];
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN];
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN];
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int num_chal;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} sim;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct {
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 rand[EAP_AKA_RAND_LEN];
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 autn[EAP_AKA_AUTN_LEN];
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 ik[EAP_AKA_IK_LEN];
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 ck[EAP_AKA_CK_LEN];
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 res[EAP_AKA_RES_MAX_LEN];
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t res_len;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} aka;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} u;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_db_data {
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int sock;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *fname;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *local_sock;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void (*get_complete_cb)(void *ctx, void *session_ctx);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *pseudonyms;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *reauths;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *pending;
694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3 *sqlite_db;
714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char db_tmp_identity[100];
724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char db_tmp_pseudonym_str[100];
734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_pseudonym db_tmp_pseudonym;
744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_reauth db_tmp_reauth;
754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_exists(sqlite3 *db, const char *name)
824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_create_pseudonym(sqlite3 *db)
904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *sql =
934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"CREATE TABLE pseudonyms("
944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  permanent CHAR(21) PRIMARY KEY,"
954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  pseudonym CHAR(21) NOT NULL"
964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		");";
974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "pseudonym information");
1004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
1014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
1074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_create_reauth(sqlite3 *db)
1114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
1134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *sql =
1144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"CREATE TABLE reauth("
1154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  permanent CHAR(21) PRIMARY KEY,"
1164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  reauth_id CHAR(21) NOT NULL,"
1174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  counter INTEGER,"
1184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  mk CHAR(40),"
1194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_encr CHAR(32),"
1204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_aut CHAR(64),"
1214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_re CHAR(64)"
1224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		");";
1234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
1254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "reauth information");
1264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
1274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
1334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic sqlite3 * db_open(const char *db_file)
1374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3 *db;
1394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_open(db_file, &db)) {
1414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: Failed to open database "
1424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "%s: %s", db_file, sqlite3_errmsg(db));
1434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!db_table_exists(db, "pseudonyms") &&
1484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    db_table_create_pseudonym(db) < 0) {
1494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!db_table_exists(db, "reauth") &&
1544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    db_table_create_reauth(db) < 0) {
1554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return db;
1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int valid_db_string(const char *str)
1644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *pos = str;
1664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (*pos) {
1674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if ((*pos < '0' || *pos > '9') &&
1684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    (*pos < 'a' || *pos > 'f'))
1694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return 0;
1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos++;
1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 1;
1734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_add_pseudonym(struct eap_sim_db_data *data,
1774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    const char *permanent, char *pseudonym)
1784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
1804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
1814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(permanent) || !valid_db_string(pseudonym)) {
1834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(pseudonym);
1844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd), "INSERT OR REPLACE INTO pseudonyms "
1884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "(permanent, pseudonym) VALUES ('%s', '%s');",
1894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    permanent, pseudonym);
1904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(pseudonym);
1914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
1924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	{
1934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
1994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int get_pseudonym_cb(void *ctx, int argc, char *argv[], char *col[])
2034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_db_data *data = ctx;
2054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int i;
2064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (i = 0; i < argc; i++) {
2084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
2094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			os_strlcpy(data->db_tmp_identity, argv[i],
2104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(data->db_tmp_identity));
2114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
2124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
2154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic char *
2194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtdb_get_pseudonym(struct eap_sim_db_data *data, const char *pseudonym)
2204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
2224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(pseudonym))
2244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memset(&data->db_tmp_identity, 0, sizeof(data->db_tmp_identity));
2264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
2274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "SELECT permanent FROM pseudonyms WHERE pseudonym='%s';",
2284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    pseudonym);
2294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, get_pseudonym_cb, data, NULL) !=
2304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    SQLITE_OK)
2314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->db_tmp_identity[0] == '\0')
2334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return data->db_tmp_identity;
2354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
2394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			 char *reauth_id, u16 counter, const u8 *mk,
2404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			 const u8 *k_encr, const u8 *k_aut, const u8 *k_re)
2414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[2000], *pos, *end;
2434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
2444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(permanent) || !valid_db_string(reauth_id)) {
2464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(reauth_id);
2474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
2484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos = cmd;
2514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	end = pos + sizeof(cmd);
2524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos += os_snprintf(pos, end - pos, "INSERT OR REPLACE INTO reauth "
2534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "(permanent, reauth_id, counter%s%s%s%s) "
2544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "VALUES ('%s', '%s', %u",
2554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   mk ? ", mk" : "",
2564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_encr ? ", k_encr" : "",
2574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_aut ? ", k_aut" : "",
2584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_re ? ", k_re" : "",
2594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   permanent, reauth_id, counter);
2604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(reauth_id);
2614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (mk) {
2634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, mk, EAP_SIM_MK_LEN);
2654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_encr) {
2694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_encr,
2714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_SIM_K_ENCR_LEN);
2724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_aut) {
2764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_aut,
2784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_AKA_PRIME_K_AUT_LEN);
2794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_re) {
2834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_re,
2854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_AKA_PRIME_K_RE_LEN);
2864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(pos, end - pos, ");");
2904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
2924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	{
2934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
2944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
2954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
2964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
2994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int get_reauth_cb(void *ctx, int argc, char *argv[], char *col[])
3034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_db_data *data = ctx;
3054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int i;
3064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_reauth *reauth = &data->db_tmp_reauth;
3074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (i = 0; i < argc; i++) {
3094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
3104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			os_strlcpy(data->db_tmp_identity, argv[i],
3114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(data->db_tmp_identity));
3124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			reauth->permanent = data->db_tmp_identity;
3134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "counter") == 0 && argv[i]) {
3144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			reauth->counter = atoi(argv[i]);
3154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "mk") == 0 && argv[i]) {
3164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->mk, sizeof(reauth->mk));
3174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_encr") == 0 && argv[i]) {
3184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_encr,
3194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_encr));
3204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_aut") == 0 && argv[i]) {
3214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_aut,
3224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_aut));
3234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_re") == 0 && argv[i]) {
3244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_re,
3254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_re));
3264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
3274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
3284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
3304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic struct eap_sim_reauth *
3344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtdb_get_reauth(struct eap_sim_db_data *data, const char *reauth_id)
3354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[256];
3374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(reauth_id))
3394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memset(&data->db_tmp_reauth, 0, sizeof(data->db_tmp_reauth));
3414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(data->db_tmp_pseudonym_str, reauth_id,
3424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   sizeof(data->db_tmp_pseudonym_str));
3434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	data->db_tmp_reauth.reauth_id = data->db_tmp_pseudonym_str;
3444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
3454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "SELECT * FROM reauth WHERE reauth_id='%s';", reauth_id);
3464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, get_reauth_cb, data, NULL) !=
3474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    SQLITE_OK)
3484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->db_tmp_reauth.permanent == NULL)
3504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return &data->db_tmp_reauth;
3524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void db_remove_reauth(struct eap_sim_db_data *data,
3564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     struct eap_sim_reauth *reauth)
3574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[256];
3594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(reauth->permanent))
3614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
3624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
3634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "DELETE FROM reauth WHERE permanent='%s';",
3644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    reauth->permanent);
3654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, NULL);
3664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
3694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eap_sim_db_pending *
3724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_pending(struct eap_sim_db_data *data, const char *imsi, int aka)
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry, *prev = NULL;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = data->pending;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
3784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (entry->aka == aka && os_strcmp(entry->imsi, imsi) == 0) {
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = entry->next;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->pending = entry->next;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return entry;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_add_pending(struct eap_sim_db_data *data,
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct eap_sim_db_pending *entry)
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->next = data->pending;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pending = entry;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *imsi, char *buf)
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *pos;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_chal;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SIM-RESP-AUTH <IMSI> Kc(i):SRES(i):RAND(i) ...
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SIM-RESP-AUTH <IMSI> FAILURE
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (IMSI = ASCII string, Kc/SRES/RAND = hex string)
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 0);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL) {
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received message found");
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(start, "FAILURE", 7) == 0) {
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->state = FAILURE;
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_add_pending(data, entry);
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_chal = 0;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_chal < EAP_SIM_MAX_CHAL) {
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(start, ' ');
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(start, ':');
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == NULL)
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos = '\0';
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.kc[num_chal],
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       EAP_SIM_KC_LEN))
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = pos + 1;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(start, ':');
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == NULL)
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos = '\0';
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.sres[num_chal],
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       EAP_SIM_SRES_LEN))
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = pos + 1;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.rand[num_chal],
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       GSM_RAND_LEN))
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_chal++;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end == NULL)
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start = end + 1;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->u.sim.num_chal = num_chal;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = SUCCESS;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "successfully - callback");
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(entry);
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data,
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *imsi, char *buf)
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * AKA-RESP-AUTH <IMSI> FAILURE
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string)
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 1);
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL) {
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received message found");
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(start, "FAILURE", 7) == 0) {
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->state = FAILURE;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_add_pending(data, entry);
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.rand, EAP_AKA_RAND_LEN))
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.autn, EAP_AKA_AUTN_LEN))
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.ik, EAP_AKA_IK_LEN))
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.ck, EAP_AKA_CK_LEN))
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end)
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end)
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->u.aka.res_len = (end - start) / 2;
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry->u.aka.res_len > EAP_AKA_RES_MAX_LEN) {
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Too long RES");
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->u.aka.res_len = 0;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.res, entry->u.aka.res_len))
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = SUCCESS;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "successfully - callback");
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(entry);
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_receive(int sock, void *eloop_ctx, void *sock_ctx)
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data = eloop_ctx;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[1000], *pos, *cmd, *imsi;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = recv(sock, buf, sizeof(buf), 0);
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-SIM DB: Received from an "
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      "external source", (u8 *) buf, res);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0)
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res >= (int) sizeof(buf))
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = sizeof(buf) - 1;
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[res] = '\0';
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->get_complete_cb == NULL) {
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No get_complete_cb "
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "registered");
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* <cmd> <IMSI> ... */
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd = buf;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strchr(cmd, ' ');
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	imsi = pos + 1;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strchr(imsi, ' ');
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: External response=%s for IMSI %s",
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   cmd, imsi);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(cmd, "SIM-RESP-AUTH") == 0)
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_sim_resp_auth(data, imsi, pos + 1);
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (os_strcmp(cmd, "AKA-RESP-AUTH") == 0)
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_aka_resp_auth(data, imsi, pos + 1);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-SIM DB: Unknown external response "
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", cmd);
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_db_open_socket(struct eap_sim_db_data *data)
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int counter = 0;
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(data->fname, "unix:", 5) != 0)
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
632cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "socket(eap_sim_db): %s", strerror(errno));
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(addr.sun_path, sizeof(addr.sun_path),
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "/tmp/eap_sim_db_%d-%d", getpid(), counter++);
64061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(data->local_sock);
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->local_sock = os_strdup(addr.sun_path);
642bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt	if (data->local_sock == NULL) {
643bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		close(data->sock);
644bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		data->sock = -1;
645bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		return -1;
646bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt	}
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
648cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "bind(eap_sim_db): %s", strerror(errno));
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, data->fname + 5, sizeof(addr.sun_path));
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (connect(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
658cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "connect(eap_sim_db): %s",
659cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			   strerror(errno));
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_INFO, "HLR/AuC GW socket",
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (u8 *) addr.sun_path,
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  os_strlen(addr.sun_path));
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
665bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		unlink(data->local_sock);
666bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		os_free(data->local_sock);
667bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		data->local_sock = NULL;
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(data->sock, eap_sim_db_receive, data, NULL);
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_close_socket(struct eap_sim_db_data *data)
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock >= 0) {
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(data->sock);
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->local_sock) {
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(data->local_sock);
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(data->local_sock);
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->local_sock = NULL;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data (e.g., file name)
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @get_complete_cb: Callback function for reporting availability of triplets
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for get_complete_cb
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a private data structure or %NULL on failure
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstruct eap_sim_db_data *
7004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_init(const char *config,
7014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		void (*get_complete_cb)(void *ctx, void *session_ctx),
7024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		void *ctx)
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data;
7054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *pos;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(sizeof(*data));
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->sock = -1;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb = get_complete_cb;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->ctx = ctx;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->fname = os_strdup(config);
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->fname == NULL)
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
7174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos = os_strstr(data->fname, " db=");
7184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (pos) {
7194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		*pos = '\0';
7204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
7214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += 4;
7224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		data->sqlite_db = db_open(pos);
7234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (data->sqlite_db == NULL)
7244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			goto fail;
7254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
7264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(data->fname, "unix:", 5) == 0) {
72961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (eap_sim_db_open_socket(data)) {
73061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: External database "
73161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "connection not available - will retry "
73261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "later");
73361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_close_socket(data);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->fname);
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p)
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(p->permanent);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p->pseudonym);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_free_reauth(struct eap_sim_reauth *r)
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(r->permanent);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(r->reauth_id);
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(r);
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_deinit - Deinitialize EAP-SIM DB/authentication gw interface
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Private data pointer from eap_sim_db_init()
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sim_db_deinit(void *priv)
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data = priv;
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p, *prev;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r, *prevr;
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *pending, *prev_pending;
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
7744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db) {
7754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(data->sqlite_db);
7764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		data->sqlite_db = NULL;
7774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
7784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
7794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_close_socket(data);
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->fname);
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = data->pseudonyms;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p) {
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = p;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p = p->next;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_free_pseudonym(prev);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r = data->reauths;
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (r) {
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prevr = r;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = r->next;
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_free_reauth(prevr);
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pending = data->pending;
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pending) {
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev_pending = pending;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pending = pending->next;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev_pending);
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_db_send(struct eap_sim_db_data *data, const char *msg,
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   size_t len)
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int _errno = 0;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (send(data->sock, msg, len, 0) < 0) {
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_errno = errno;
815cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "send[EAP-SIM DB UNIX]: %s",
816cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			   strerror(errno));
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    _errno == ECONNREFUSED) {
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to reconnect */
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_close_socket(data);
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Reconnected to the "
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "external server");
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (send(data->sock, msg, len, 0) < 0) {
828cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			wpa_printf(MSG_INFO, "send[EAP-SIM DB UNIX]: %s",
829cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				   strerror(errno));
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_expire_pending(struct eap_sim_db_data *data)
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add limit for maximum length for pending list; remove latest
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (i.e., last) entry from the list if the limit is reached; could also
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * use timeout to expire pending entries */
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_gsm_triplets - Get GSM triplets
8484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
8494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username (prefix | IMSI)
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @max_chal: Maximum number of triplets
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: Buffer for RAND values
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kc: Buffer for Kc values
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sres: Buffer for SRES values
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb_session_ctx: Session callback context for get_complete_cb()
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of triplets received (has to be less than or equal to
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * max_chal), -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not found), or
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this case, the
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * callback function registered with eap_sim_db_init() will be called once the
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * results become available.
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using an external server for GSM triplets, this function can always
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * start a request and return EAP_SIM_DB_PENDING immediately if authentication
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * triplets are not available. Once the triplets are received, callback
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function registered with eap_sim_db_init() is called to notify EAP state
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * machine to reprocess the message. This eap_sim_db_get_gsm_triplets()
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function will then be called again and the newly received triplets will then
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be given to the caller.
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
8694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_get_gsm_triplets(struct eap_sim_db_data *data,
8704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const char *username, int max_chal,
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				u8 *_rand, u8 *kc, u8 *sres,
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void *cb_session_ctx)
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, ret;
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char msg[40];
8774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
8784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL || username[0] != EAP_SIM_PERMANENT_PREFIX ||
8814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
8824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
8834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
8874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI '%s'",
8884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 0);
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int num_chal;
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == FAILURE) {
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failure");
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(entry);
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == PENDING) {
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "still pending");
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_add_pending(data, entry);
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_PENDING;
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d challenges", entry->u.sim.num_chal);
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_chal = entry->u.sim.num_chal;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_chal > max_chal)
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			num_chal = max_chal;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN);
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sres, entry->u.sim.sres,
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_chal * EAP_SIM_SRES_LEN);
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(entry);
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return num_chal;
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi_len = os_strlen(imsi);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(msg, sizeof(msg), "SIM-REQ-AUTH ");
9274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (len < 0 || len + imsi_len >= sizeof(msg))
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memcpy(msg + len, imsi, imsi_len);
9304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	len += imsi_len;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(msg + len, sizeof(msg) - len, " %d", max_chal);
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || (size_t) ret >= sizeof(msg) - len)
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len += ret;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting SIM authentication "
9374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "data for IMSI '%s'", imsi);
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sim_db_send(data, msg, len) < 0)
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = os_zalloc(sizeof(*entry));
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL)
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->cb_session_ctx = cb_session_ctx;
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = PENDING;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_expire_pending(data);
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_SIM_DB_PENDING;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix)
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *id, *pos, *end;
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[10];
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(buf, sizeof(buf)))
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	id = os_malloc(sizeof(buf) * 2 + 2);
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (id == NULL)
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = id;
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = id + sizeof(buf) * 2 + 2;
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = prefix;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, buf, sizeof(buf));
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return id;
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_next_pseudonym - EAP-SIM DB: Get next pseudonym
9774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
97804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @method: EAP method (SIM/AKA/AKA')
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Next pseudonym (allocated string) or %NULL on failure
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to generate a pseudonym for EAP-SIM. The returned
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pseudonym is not added to database at this point; it will need to be added
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with eap_sim_db_add_pseudonym() once the authentication has been completed
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successfully. Caller is responsible for freeing the returned buffer.
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
9864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * eap_sim_db_get_next_pseudonym(struct eap_sim_db_data *data,
9874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     enum eap_sim_db_method method)
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
98904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
99004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
99104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
99204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_SIM:
99304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_SIM_PSEUDONYM_PREFIX;
99404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
99504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA:
99604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PSEUDONYM_PREFIX;
99704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
99804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA_PRIME:
99904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PRIME_PSEUDONYM_PREFIX;
100004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
100104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
100204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
100304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return eap_sim_db_get_next(data, prefix);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_next_reauth_id - EAP-SIM DB: Get next reauth_id
10094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
101004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @method: EAP method (SIM/AKA/AKA')
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Next reauth_id (allocated string) or %NULL on failure
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to generate a fast re-authentication identity for
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM. The returned reauth_id is not added to database at this point; it
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will need to be added with eap_sim_db_add_reauth() once the authentication
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has been completed successfully. Caller is responsible for freeing the
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * returned buffer.
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * eap_sim_db_get_next_reauth_id(struct eap_sim_db_data *data,
10204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     enum eap_sim_db_method method)
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
102204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
102304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
102404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
102504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_SIM:
102604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_SIM_REAUTH_ID_PREFIX;
102704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
102804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA:
102904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_REAUTH_ID_PREFIX;
103004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
103104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA_PRIME:
103204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PRIME_REAUTH_ID_PREFIX;
103304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
103404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
103504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
103604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return eap_sim_db_get_next(data, prefix);
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_pseudonym - EAP-SIM DB: Add new pseudonym
10424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
10434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pseudonym: Pseudonym for this user. This needs to be an allocated buffer,
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_pseudonym(). Caller must not
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new pseudonym for EAP-SIM user. EAP-SIM DB is
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * responsible of freeing pseudonym buffer once it is not needed anymore.
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_pseudonym(struct eap_sim_db_data *data,
10534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const char *permanent, char *pseudonym)
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p;
10564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add pseudonym '%s' for permanent "
10574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "username '%s'", pseudonym, permanent);
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: could store last two pseudonyms */
10604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
10614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
10624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_pseudonym(data, permanent, pseudonym);
10634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
10644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (p = data->pseudonyms; p; p = p->next) {
10654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(permanent, p->permanent) == 0)
10664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
10674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p) {
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "pseudonym: %s", p->pseudonym);
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p->pseudonym);
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p->pseudonym = pseudonym;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = os_zalloc(sizeof(*p));
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p == NULL) {
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pseudonym);
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->next = data->pseudonyms;
10834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	p->permanent = os_strdup(permanent);
10844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (p->permanent == NULL) {
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p);
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pseudonym);
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->pseudonym = pseudonym;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pseudonyms = p;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new pseudonym entry");
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eap_sim_reauth *
10984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_add_reauth_data(struct eap_sim_db_data *data,
10994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   const char *permanent,
11004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   char *reauth_id, u16 counter)
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (r = data->reauths; r; r = r->next) {
11054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(r->permanent, permanent) == 0)
11064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
11074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r) {
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "reauth_id: %s", r->reauth_id);
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(r->reauth_id);
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->reauth_id = reauth_id;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = os_zalloc(sizeof(*r));
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == NULL) {
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(reauth_id);
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->next = data->reauths;
11224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		r->permanent = os_strdup(permanent);
11234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (r->permanent == NULL) {
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(r);
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(reauth_id);
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->reauth_id = reauth_id;
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->reauths = r;
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new reauth entry");
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r->counter = counter;
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return r;
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Private data pointer from eap_sim_db_init()
11424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identity_len: Length of identity
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @counter: AT_COUNTER value for fast re-authentication
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mk: 16-byte MK from the previous full authentication or %NULL
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new re-authentication entry for an EAP-SIM user.
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * anymore.
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
11554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
11564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  char *reauth_id, u16 counter, const u8 *mk)
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
11614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "identity '%s'", reauth_id, permanent);
11624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
11634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
11644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
11654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_reauth(data, permanent, reauth_id, counter, mk,
11664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     NULL, NULL, NULL);
11674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
11684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r == NULL)
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->mk, mk, EAP_SIM_MK_LEN);
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry
11814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
11824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @counter: AT_COUNTER value for fast re-authentication
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_encr: K_encr from the previous full authentication
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_aut: K_aut from the previous full authentication
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_re: 32-byte K_re from the previous full authentication
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new re-authentication entry for an EAP-AKA' user.
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * anymore.
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
11964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_reauth_prime(struct eap_sim_db_data *data,
11974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const char *permanent, char *reauth_id,
11984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				u16 counter, const u8 *k_encr,
11994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const u8 *k_aut, const u8 *k_re)
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
12044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "identity '%s'", reauth_id, permanent);
12054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
12064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_reauth(data, permanent, reauth_id, counter, NULL,
12094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     k_encr, k_aut, k_re);
12104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r == NULL)
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_encr, k_encr, EAP_SIM_K_ENCR_LEN);
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_aut, k_aut, EAP_AKA_PRIME_K_AUT_LEN);
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_re, k_re, EAP_AKA_PRIME_K_RE_LEN);
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_permanent - EAP-SIM DB: Get permanent identity
12264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @pseudonym: Pseudonym username
12284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Returns: Pointer to permanent username or %NULL if not found
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtconst char *
12314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_permanent(struct eap_sim_db_data *data, const char *pseudonym)
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_get_pseudonym(data, pseudonym);
12384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	p = data->pseudonyms;
12414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (p) {
12424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(p->pseudonym, pseudonym) == 0)
12434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return p->permanent;
12444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		p = p->next;
12454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return NULL;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_reauth_entry - EAP-SIM DB: Get re-authentication entry
12534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @reauth_id: Fast re-authentication username
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the re-auth entry, or %NULL if not found
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_reauth *
12584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_reauth_entry(struct eap_sim_db_data *data,
12594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    const char *reauth_id)
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_get_reauth(data, reauth_id);
12664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
12684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = data->reauths;
12694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (r) {
12704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(r->reauth_id, reauth_id) == 0)
12714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
12724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		r = r->next;
12734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
12744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return r;
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_remove_reauth - EAP-SIM DB: Remove re-authentication entry
12814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth: Pointer to re-authentication entry from
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_reauth_entry()
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtvoid eap_sim_db_remove_reauth(struct eap_sim_db_data *data,
12864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			      struct eap_sim_reauth *reauth)
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r, *prev = NULL;
12894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db) {
12914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		db_remove_reauth(data, reauth);
12924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
12934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
12944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r = data->reauths;
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (r) {
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == reauth) {
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = r->next;
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->reauths = r->next;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_free_reauth(r);
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = r;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = r->next;
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth - Get AKA authentication values
13134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
13144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username (prefix | IMSI)
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: Buffer for RAND value
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @autn: Buffer for AUTN value
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ik: Buffer for IK value
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ck: Buffer for CK value
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @res: Buffer for RES value
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @res_len: Buffer for RES length
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb_session_ctx: Session callback context for get_complete_cb()
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * found), or -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * case, the callback function registered with eap_sim_db_init() will be
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * called once the results become available.
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using an external server for AKA authentication, this function can
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * always start a request and return EAP_SIM_DB_PENDING immediately if
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication triplets are not available. Once the authentication data are
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received, callback function registered with eap_sim_db_init() is called to
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notify EAP state machine to reprocess the message. This
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth() function will then be called again and the newly
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received triplets will then be given to the caller.
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_get_aka_auth(struct eap_sim_db_data *data, const char *username,
13364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    u8 *_rand, u8 *autn, u8 *ik, u8 *ck,
13374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    u8 *res, size_t *res_len, void *cb_session_ctx)
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char msg[40];
13424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
13434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL ||
13464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    (username[0] != EAP_AKA_PERMANENT_PREFIX &&
13474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	     username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
13484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
13494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
13504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
13544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
13554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 1);
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == FAILURE) {
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(entry);
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == PENDING) {
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_add_pending(data, entry);
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending");
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_PENDING;
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Returning successfully "
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received authentication data");
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN);
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN);
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN);
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*res_len = entry->u.aka.res_len;
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(entry);
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi_len = os_strlen(imsi);
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(msg, sizeof(msg), "AKA-REQ-AUTH ");
13904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (len < 0 || len + imsi_len >= sizeof(msg))
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
13924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memcpy(msg + len, imsi, imsi_len);
13934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	len += imsi_len;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting AKA authentication "
13964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "data for IMSI '%s'", imsi);
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sim_db_send(data, msg, len) < 0)
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = os_zalloc(sizeof(*entry));
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL)
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->aka = 1;
14054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->cb_session_ctx = cb_session_ctx;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = PENDING;
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_expire_pending(data);
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_SIM_DB_PENDING;
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_resynchronize - Resynchronize AKA AUTN
14174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
14184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auts: AUTS value from the peer
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: RAND value used in the rejected message
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when the peer reports synchronization failure in the
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AUTN value by sending AUTS. The AUTS and RAND values should be sent to
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HLR/AuC to allow it to resynchronize with the peer. After this,
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth() will be called again to to fetch updated
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RAND/AUTN values for the next challenge.
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_resynchronize(struct eap_sim_db_data *data,
14304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const char *username,
14314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const u8 *auts, const u8 *_rand)
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
14344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL ||
14374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    (username[0] != EAP_AKA_PERMANENT_PREFIX &&
14384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	     username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
14394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > 20) {
14404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
14414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
14454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
14464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock >= 0) {
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char msg[100];
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int len, ret;
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		imsi_len = os_strlen(imsi);
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_snprintf(msg, sizeof(msg), "AKA-AUTS ");
14544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (len < 0 || len + imsi_len >= sizeof(msg))
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_memcpy(msg + len, imsi, imsi_len);
14574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		len += imsi_len;
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || (size_t) ret >= sizeof(msg) - len)
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					auts, EAP_AKA_AUTS_LEN);
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || (size_t) ret >= sizeof(msg) - len)
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					_rand, EAP_AKA_RAND_LEN);
14714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: reporting AKA AUTS for "
14724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "IMSI '%s'", imsi);
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_send(data, msg, len) < 0)
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt/**
14824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * sim_get_username - Extract username from SIM identity
14834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @identity: Identity
14844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @identity_len: Identity length
14854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Returns: Allocated buffer with the username part of the identity
14864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt *
14874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Caller is responsible for freeing the returned buffer with os_free().
14884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */
14894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * sim_get_username(const u8 *identity, size_t identity_len)
14904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
14914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t pos;
14924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (identity == NULL)
14944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
14954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (pos = 0; pos < identity_len; pos++) {
14974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (identity[pos] == '@' || identity[pos] == '\0')
14984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
14994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
15004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
15014b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	return dup_binstr(identity, pos);
15024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1503