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>
This commit is contained in:
Jouni Malinen 2012-08-30 16:55:36 +03:00 committed by Jouni Malinen
parent 66979bb833
commit 29813cfdc0

View file

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