aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2012-08-30 13:55:36 (GMT)
committerJouni Malinen <j@w1.fi>2012-08-30 13:55:36 (GMT)
commit29813cfdc0b04363fe741971c17937732598e7d4 (patch)
tree677fcab9ca72d57f109f2c4c28a88fc506ed4b4a
parent66979bb833047cce3d935e24072b1af4b356e6fe (diff)
downloadhostap-29813cfdc0b04363fe741971c17937732598e7d4.zip
hostap-29813cfdc0b04363fe741971c17937732598e7d4.tar.gz
hostap-29813cfdc0b04363fe741971c17937732598e7d4.tar.bz2
EAP-SIM DB: Optional use of SQLite database for reauth data
If hostapd is built and configured to use SQLite database, store EAP-SIM/AKA reauth data into the database to allow this to persist over hostapd restarts. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
-rw-r--r--src/eap_server/eap_sim_db.c256
1 files changed, 255 insertions, 1 deletions
diff --git a/src/eap_server/eap_sim_db.c b/src/eap_server/eap_sim_db.c
index a9921ac..a1a0fd2 100644
--- a/src/eap_server/eap_sim_db.c
+++ b/src/eap_server/eap_sim_db.c
@@ -74,6 +74,7 @@ struct eap_sim_db_data {
u8 db_tmp_identity[100];
char db_tmp_pseudonym_str[100];
struct eap_sim_pseudonym db_tmp_pseudonym;
+ struct eap_sim_reauth db_tmp_reauth;
#endif /* CONFIG_SQLITE */
};
@@ -109,6 +110,33 @@ static int db_table_create_pseudonym(sqlite3 *db)
}
+static int db_table_create_reauth(sqlite3 *db)
+{
+ char *err = NULL;
+ const char *sql =
+ "CREATE TABLE reauth("
+ " imsi INTEGER PRIMARY KEY NOT NULL,"
+ " reauth_id CHAR(21) NOT NULL,"
+ " counter INTEGER,"
+ " aka_prime BOOL,"
+ " mk CHAR(40),"
+ " k_encr CHAR(32),"
+ " k_aut CHAR(64),"
+ " k_re CHAR(64)"
+ ");";
+
+ wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
+ "reauth information");
+ if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
+ wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
+ sqlite3_free(err);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static sqlite3 * db_open(const char *db_file)
{
sqlite3 *db;
@@ -126,6 +154,12 @@ static sqlite3 * db_open(const char *db_file)
return NULL;
}
+ if (!db_table_exists(db, "reauth") &&
+ db_table_create_reauth(db) < 0) {
+ sqlite3_close(db);
+ return NULL;
+ }
+
return db;
}
@@ -148,6 +182,7 @@ static int db_add_pseudonym(struct eap_sim_db_data *data, const u8 *identity,
{
char cmd[128];
unsigned long long imsi;
+ char *err = NULL;
if (!valid_pseudonym_string(pseudonym) || identity_len >= sizeof(cmd))
{
@@ -162,8 +197,12 @@ static int db_add_pseudonym(struct eap_sim_db_data *data, const u8 *identity,
"(imsi, pseudonym) VALUES (%llu , '%s');",
imsi, pseudonym);
os_free(pseudonym);
- if (sqlite3_exec(data->sqlite_db, cmd, NULL, data, NULL) != SQLITE_OK)
+ if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
+ {
+ wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
+ sqlite3_free(err);
return -1;
+ }
return 0;
}
@@ -251,8 +290,192 @@ db_get_pseudonym_id(struct eap_sim_db_data *data, const u8 *identity,
return &data->db_tmp_pseudonym;
}
+
+static int db_add_reauth(struct eap_sim_db_data *data, const u8 *identity,
+ size_t identity_len, char *reauth_id, u16 counter,
+ const u8 *mk, int aka_prime, const u8 *k_encr,
+ const u8 *k_aut, const u8 *k_re)
+{
+ char cmd[2000], *pos, *end;
+ unsigned long long imsi;
+ char *err = NULL;
+
+ if (!valid_pseudonym_string(reauth_id) || identity_len >= sizeof(cmd))
+ {
+ os_free(reauth_id);
+ return -1;
+ }
+ os_memcpy(cmd, identity, identity_len);
+ cmd[identity_len] = '\0';
+ imsi = atoll(cmd);
+
+ pos = cmd;
+ end = pos + sizeof(cmd);
+ pos += os_snprintf(pos, end - pos, "INSERT OR REPLACE INTO reauth "
+ "(imsi, reauth_id, counter, aka_prime%s%s%s%s) "
+ "VALUES (%llu, '%s', %u, %d",
+ mk ? ", mk" : "",
+ k_encr ? ", k_encr" : "",
+ k_aut ? ", k_aut" : "",
+ k_re ? ", k_re" : "",
+ imsi, reauth_id, counter, aka_prime);
+ os_free(reauth_id);
+
+ if (mk) {
+ pos += os_snprintf(pos, end - pos, ", '");
+ pos += wpa_snprintf_hex(pos, end - pos, mk, EAP_SIM_MK_LEN);
+ pos += os_snprintf(pos, end - pos, "'");
+ }
+
+ if (k_encr) {
+ pos += os_snprintf(pos, end - pos, ", '");
+ pos += wpa_snprintf_hex(pos, end - pos, k_encr,
+ EAP_SIM_K_ENCR_LEN);
+ pos += os_snprintf(pos, end - pos, "'");
+ }
+
+ if (k_aut) {
+ pos += os_snprintf(pos, end - pos, ", '");
+ pos += wpa_snprintf_hex(pos, end - pos, k_aut,
+ EAP_AKA_PRIME_K_AUT_LEN);
+ pos += os_snprintf(pos, end - pos, "'");
+ }
+
+ if (k_re) {
+ pos += os_snprintf(pos, end - pos, ", '");
+ pos += wpa_snprintf_hex(pos, end - pos, k_re,
+ EAP_AKA_PRIME_K_RE_LEN);
+ pos += os_snprintf(pos, end - pos, "'");
+ }
+
+ os_snprintf(pos, end - pos, ");");
+
+ if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
+ {
+ wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
+ sqlite3_free(err);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int get_reauth_cb(void *ctx, int argc, char *argv[], char *col[])
+{
+ struct eap_sim_db_data *data = ctx;
+ int i;
+ size_t len;
+ struct eap_sim_reauth *reauth = &data->db_tmp_reauth;
+
+ for (i = 0; i < argc; i++) {
+ if (os_strcmp(col[i], "imsi") == 0 && argv[i]) {
+ len = os_strlen(argv[i]);
+ if (len > sizeof(data->db_tmp_identity))
+ continue;
+ os_memcpy(data->db_tmp_identity, argv[i], len);
+ reauth->identity = data->db_tmp_identity;
+ reauth->identity_len = len;
+ } else if (os_strcmp(col[i], "reauth_id") == 0 && argv[i]) {
+ len = os_strlen(argv[i]);
+ if (len >= sizeof(data->db_tmp_pseudonym_str))
+ continue;
+ os_memcpy(data->db_tmp_pseudonym_str, argv[i], len);
+ data->db_tmp_pseudonym_str[len] = '\0';
+ reauth->reauth_id = data->db_tmp_pseudonym_str;
+ } else if (os_strcmp(col[i], "counter") == 0 && argv[i]) {
+ reauth->counter = atoi(argv[i]);
+ } else if (os_strcmp(col[i], "aka_prime") == 0 && argv[i]) {
+ reauth->aka_prime = atoi(argv[i]);
+ } else if (os_strcmp(col[i], "mk") == 0 && argv[i]) {
+ hexstr2bin(argv[i], reauth->mk, sizeof(reauth->mk));
+ } else if (os_strcmp(col[i], "k_encr") == 0 && argv[i]) {
+ hexstr2bin(argv[i], reauth->k_encr,
+ sizeof(reauth->k_encr));
+ } else if (os_strcmp(col[i], "k_aut") == 0 && argv[i]) {
+ hexstr2bin(argv[i], reauth->k_aut,
+ sizeof(reauth->k_aut));
+ } else if (os_strcmp(col[i], "k_re") == 0 && argv[i]) {
+ hexstr2bin(argv[i], reauth->k_re,
+ sizeof(reauth->k_re));
+ }
+ }
+
+ return 0;
+}
+
+
+static struct eap_sim_reauth *
+db_get_reauth(struct eap_sim_db_data *data, const char *reauth_id)
+{
+ char cmd[256];
+
+ if (!valid_pseudonym_string(reauth_id))
+ return NULL;
+ os_memset(&data->db_tmp_reauth, 0, sizeof(data->db_tmp_reauth));
+ os_strlcpy(data->db_tmp_pseudonym_str, reauth_id,
+ sizeof(data->db_tmp_pseudonym_str));
+ data->db_tmp_reauth.reauth_id = data->db_tmp_pseudonym_str;
+ os_snprintf(cmd, sizeof(cmd),
+ "SELECT * FROM reauth WHERE reauth_id='%s';", reauth_id);
+ if (sqlite3_exec(data->sqlite_db, cmd, get_reauth_cb, data, NULL) !=
+ SQLITE_OK)
+ return NULL;
+ if (data->db_tmp_reauth.identity == NULL)
+ return NULL;
+ return &data->db_tmp_reauth;
+}
+
+
+static struct eap_sim_reauth *
+db_get_reauth_id(struct eap_sim_db_data *data, const u8 *identity,
+ size_t identity_len)
+{
+ char cmd[256];
+ unsigned long long imsi;
+
+ if (identity_len >= sizeof(cmd))
+ return NULL;
+ os_memcpy(cmd, identity, identity_len);
+ cmd[identity_len] = '\0';
+ imsi = atoll(cmd);
+
+ os_memset(&data->db_tmp_reauth, 0, sizeof(data->db_tmp_reauth));
+ if (identity_len > sizeof(data->db_tmp_identity))
+ return NULL;
+ os_memcpy(data->db_tmp_identity, identity, identity_len);
+ data->db_tmp_reauth.identity = data->db_tmp_identity;
+ data->db_tmp_reauth.identity_len = identity_len;
+ os_snprintf(cmd, sizeof(cmd),
+ "SELECT * FROM reauth WHERE imsi=%llu;", imsi);
+ if (sqlite3_exec(data->sqlite_db, cmd, get_reauth_cb, data, NULL) !=
+ SQLITE_OK)
+ return NULL;
+ if (data->db_tmp_reauth.reauth_id == NULL)
+ return NULL;
+ return &data->db_tmp_reauth;
+}
+
+
+static void db_remove_reauth(struct eap_sim_db_data *data,
+ struct eap_sim_reauth *reauth)
+{
+ char cmd[256];
+ unsigned long long imsi;
+
+ if (reauth->identity_len >= sizeof(cmd))
+ return;
+ os_memcpy(cmd, reauth->identity, reauth->identity_len);
+ cmd[reauth->identity_len] = '\0';
+ imsi = atoll(cmd);
+ os_snprintf(cmd, sizeof(cmd),
+ "DELETE FROM reauth WHERE imsi=%llu;", imsi);
+ sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, NULL);
+}
+
#endif /* CONFIG_SQLITE */
+
static struct eap_sim_db_pending *
eap_sim_db_get_pending(struct eap_sim_db_data *data, const u8 *imsi,
size_t imsi_len, int aka)
@@ -949,6 +1172,14 @@ eap_sim_db_get_reauth(struct eap_sim_db_data *data, const u8 *identity,
os_memcpy(reauth_id, identity, len);
reauth_id[len] = '\0';
+#ifdef CONFIG_SQLITE
+ if (data->sqlite_db) {
+ r = db_get_reauth(data, reauth_id);
+ os_free(reauth_id);
+ return r;
+ }
+#endif /* CONFIG_SQLITE */
+
r = data->reauths;
while (r) {
if (os_strcmp(r->reauth_id, reauth_id) == 0)
@@ -980,6 +1211,11 @@ eap_sim_db_get_reauth_id(struct eap_sim_db_data *data, const u8 *identity,
identity_len = p->identity_len;
}
+#ifdef CONFIG_SQLITE
+ if (data->sqlite_db)
+ return db_get_reauth_id(data, identity, identity_len);
+#endif /* CONFIG_SQLITE */
+
r = data->reauths;
while (r) {
if (identity_len == r->identity_len &&
@@ -1263,6 +1499,12 @@ int eap_sim_db_add_reauth(void *priv, const u8 *identity,
struct eap_sim_db_data *data = priv;
struct eap_sim_reauth *r;
+#ifdef CONFIG_SQLITE
+ if (data->sqlite_db)
+ return db_add_reauth(data, identity, identity_len,
+ reauth_id, counter, mk, 0, NULL, NULL,
+ NULL);
+#endif /* CONFIG_SQLITE */
r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id,
counter);
if (r == NULL)
@@ -1302,6 +1544,12 @@ int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity,
struct eap_sim_db_data *data = priv;
struct eap_sim_reauth *r;
+#ifdef CONFIG_SQLITE
+ if (data->sqlite_db)
+ return db_add_reauth(data, identity, identity_len,
+ reauth_id, counter, NULL, 1,
+ k_encr, k_aut, k_re);
+#endif /* CONFIG_SQLITE */
r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id,
counter);
if (r == NULL)
@@ -1379,6 +1627,12 @@ void eap_sim_db_remove_reauth(void *priv, struct eap_sim_reauth *reauth)
{
struct eap_sim_db_data *data = priv;
struct eap_sim_reauth *r, *prev = NULL;
+#ifdef CONFIG_SQLITE
+ if (data->sqlite_db) {
+ db_remove_reauth(data, reauth);
+ return;
+ }
+#endif /* CONFIG_SQLITE */
r = data->reauths;
while (r) {
if (r == reauth) {