18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2005-2007, 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 to HLR/AuC. It is expected to be replaced with an
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a local implementation of SIM triplet and AKA authentication data generator.
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd will send SIM/AKA authentication queries over a UNIX domain socket
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to and external program, e.g., this hlr_auc_gw. This interface uses simple
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * text-based format:
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM / GSM triplet query/response:
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SIM-REQ-AUTH <IMSI> <max_chal>
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3]
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SIM-RESP-AUTH <IMSI> FAILURE
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-AKA / UMTS query/response:
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-REQ-AUTH <IMSI>
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-RESP-AUTH <IMSI> FAILURE
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-AKA / UMTS AUTS (re-synchronization):
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-AUTS <IMSI> <AUTS> <RAND>
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IMSI and max_chal are sent as an ASCII string,
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The example implementation here reads GSM authentication triplets from a
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * strings. This is used to simulate an HLR/AuC. As such, it is not very useful
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for real life authentication, but it is useful both as an example
3704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * implementation and for EAP-SIM/AKA/AKA' testing.
3804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *
3904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * SQN generation follows the not time-based Profile 2 described in
4004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this
4104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * can be changed with a command line options if needed.
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/un.h>
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include <sqlite3.h>
4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/milenage.h"
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *socket_path;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int serv_sock = -1;
5704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic char *milenage_file = NULL;
5804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int update_milenage = 0;
5904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int sqn_changes = 0;
6004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int ind_len = 5;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* GSM triplets */
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct gsm_triplet {
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct gsm_triplet *next;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[20];
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 kc[8];
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 sres[4];
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 _rand[16];
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct milenage_parameters {
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct milenage_parameters *next;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[20];
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 ki[16];
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 opc[16];
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 amf[2];
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 sqn[6];
814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int set;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct milenage_parameters *milenage_db = NULL;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_SIM_MAX_CHAL 3
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_RAND_LEN 16
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_AUTN_LEN 16
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_AUTS_LEN 14
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_RES_MAX_LEN 16
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_IK_LEN 16
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_CK_LEN 16
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic sqlite3 *sqlite_db = NULL;
9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct milenage_parameters db_tmp_milenage;
10061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int db_table_exists(sqlite3 *db, const char *name)
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char cmd[128];
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int db_table_create_milenage(sqlite3 *db)
11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *err = NULL;
11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const char *sql =
11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"CREATE TABLE milenage("
11561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"  imsi INTEGER PRIMARY KEY NOT NULL,"
11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"  ki CHAR(32) NOT NULL,"
11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"  opc CHAR(32) NOT NULL,"
11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"  amf CHAR(4) NOT NULL,"
11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		"  sqn CHAR(12) NOT NULL"
12061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		");";
12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	printf("Adding database table for milenage information\n");
12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		printf("SQLite error: %s\n", err);
12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sqlite3_free(err);
12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
13061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic sqlite3 * db_open(const char *db_file)
13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sqlite3 *db;
13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sqlite3_open(db_file, &db)) {
13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		printf("Failed to open database %s: %s\n",
13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		       db_file, sqlite3_errmsg(db));
14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sqlite3_close(db);
14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return NULL;
14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
14461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!db_table_exists(db, "milenage") &&
14561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    db_table_create_milenage(db) < 0) {
14661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sqlite3_close(db);
14761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return NULL;
14861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
14961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return db;
15161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
15561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
15661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct milenage_parameters *m = ctx;
15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int i;
15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	m->set = 1;
1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (i = 0; i < argc; i++) {
16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (os_strcmp(col[i], "ki") == 0 && argv[i] &&
16361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    hexstr2bin(argv[i], m->ki, sizeof(m->ki))) {
16461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			printf("Invalid ki value in database\n");
16561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
16661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
16761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
16861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (os_strcmp(col[i], "opc") == 0 && argv[i] &&
16961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    hexstr2bin(argv[i], m->opc, sizeof(m->opc))) {
17061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			printf("Invalid opcvalue in database\n");
17161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
17261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (os_strcmp(col[i], "amf") == 0 && argv[i] &&
17561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    hexstr2bin(argv[i], m->amf, sizeof(m->amf))) {
17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			printf("Invalid amf value in database\n");
17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (os_strcmp(col[i], "sqn") == 0 && argv[i] &&
18161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    hexstr2bin(argv[i], m->sqn, sizeof(m->sqn))) {
18261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			printf("Invalid sqn value in database\n");
18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct milenage_parameters * db_get_milenage(const char *imsi_txt)
19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char cmd[128];
19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	unsigned long long imsi;
19561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memset(&db_tmp_milenage, 0, sizeof(db_tmp_milenage));
19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	imsi = atoll(imsi_txt);
19861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
19961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    "%llu", imsi);
20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    "SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    imsi);
20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 NULL) != SQLITE_OK)
20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return NULL;
20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!db_tmp_milenage.set)
2084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
20961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return &db_tmp_milenage;
21061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
21161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int db_update_milenage_sqn(struct milenage_parameters *m)
21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char cmd[128], val[13], *pos;
21661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = val;
21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	*pos = '\0';
22061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
22161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    "UPDATE milenage SET sqn='%s' WHERE imsi=%s;",
22261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    val, m->imsi);
22361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sqlite3_exec(sqlite_db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		printf("Failed to update SQN in database for IMSI %s\n",
22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		       m->imsi);
22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
23261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
23361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int open_socket(const char *path)
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int s;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	s = socket(PF_UNIX, SOCK_DGRAM, 0);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (s < 0) {
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("socket(PF_UNIX)");
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	memset(&addr, 0, sizeof(addr));
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
24904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		perror("hlr-auc-gw: bind(PF_UNIX)");
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(s);
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return s;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int read_gsm_triplets(const char *fname)
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[200], *pos, *pos2;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct gsm_triplet *g = NULL;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int line, ret = 0;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fname == NULL)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(fname, "r");
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL) {
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not open GSM tripler data file '%s'\n", fname);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	line = 0;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (fgets(buf, sizeof(buf), f)) {
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		line++;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Parse IMSI:Kc:SRES:RAND */
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[sizeof(buf) - 1] = '\0';
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf[0] == '#')
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = buf;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos != '\0' && *pos != '\n')
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\n')
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos = '\0';
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = buf;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0')
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		g = os_zalloc(sizeof(*g));
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (g == NULL) {
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IMSI */
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ':');
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == NULL) {
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid IMSI (%s)\n",
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       fname, line, pos);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos2 = '\0';
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) >= sizeof(g->imsi)) {
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Too long IMSI (%s)\n",
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       fname, line, pos);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(g->imsi, pos, sizeof(g->imsi));
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Kc */
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ':');
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == NULL) {
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos2 = '\0';
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* SRES */
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ':');
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == NULL) {
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid SRES (%s)\n", fname, line,
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       pos);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos2 = '\0';
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) {
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid SRES (%s)\n", fname, line,
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       pos);
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* RAND */
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ':');
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2)
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos2 = '\0';
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) {
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid RAND (%s)\n", fname, line,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       pos);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		g->next = gsm_db;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gsm_db = g;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		g = NULL;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
36304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(g);
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct gsm_triplet * get_gsm_triplet(const char *imsi)
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct gsm_triplet *g = gsm_db_pos;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (g) {
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strcmp(g->imsi, imsi) == 0) {
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gsm_db_pos = g->next;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return g;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		g = g->next;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	g = gsm_db;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (g && g != gsm_db_pos) {
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strcmp(g->imsi, imsi) == 0) {
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gsm_db_pos = g->next;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return g;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		g = g->next;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int read_milenage(const char *fname)
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[200], *pos, *pos2;
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct milenage_parameters *m = NULL;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int line, ret = 0;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fname == NULL)
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(fname, "r");
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL) {
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not open Milenage data file '%s'\n", fname);
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	line = 0;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (fgets(buf, sizeof(buf), f)) {
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		line++;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Parse IMSI Ki OPc AMF SQN */
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[sizeof(buf) - 1] = '\0';
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf[0] == '#')
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = buf;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*pos != '\0' && *pos != '\n')
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\n')
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos = '\0';
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = buf;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == '\0')
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m = os_zalloc(sizeof(*m));
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (m == NULL) {
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IMSI */
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ' ');
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == NULL) {
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid IMSI (%s)\n",
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       fname, line, pos);
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos2 = '\0';
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) >= sizeof(m->imsi)) {
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Too long IMSI (%s)\n",
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       fname, line, pos);
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(m->imsi, pos, sizeof(m->imsi));
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ki */
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ' ');
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == NULL) {
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos2 = '\0';
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) {
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* OPc */
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ' ');
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == NULL) {
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos2 = '\0';
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) {
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* AMF */
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ' ');
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == NULL) {
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos2 = '\0';
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* SQN */
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = strchr(pos, ' ');
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2)
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*pos2 = '\0';
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) {
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m->next = milenage_db;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		milenage_db = m;
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m = NULL;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
51304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(m);
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
52104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void update_milenage_file(const char *fname)
52204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
52304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	FILE *f, *f2;
52404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char buf[500], *pos;
52504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char *end = buf + sizeof(buf);
52604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct milenage_parameters *m;
52704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	size_t imsi_len;
52804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
52904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	f = fopen(fname, "r");
53004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (f == NULL) {
53104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Could not open Milenage data file '%s'\n", fname);
53204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
53304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
53404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
53504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	snprintf(buf, sizeof(buf), "%s.new", fname);
53604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	f2 = fopen(buf, "w");
53704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (f2 == NULL) {
53804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Could not write Milenage data file '%s'\n", buf);
53904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		fclose(f);
54004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
54104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
54204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
54304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	while (fgets(buf, sizeof(buf), f)) {
54404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* IMSI Ki OPc AMF SQN */
54504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		buf[sizeof(buf) - 1] = '\0';
54604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
54704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos = strchr(buf, ' ');
54804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (buf[0] == '#' || pos == NULL || pos - buf >= 20)
54904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			goto no_update;
55004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
55104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		imsi_len = pos - buf;
55204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
55304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		for (m = milenage_db; m; m = m->next) {
55404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (strncmp(buf, m->imsi, imsi_len) == 0 &&
55504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    m->imsi[imsi_len] == '\0')
55604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				break;
55704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
55804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
55904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!m)
56004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			goto no_update;
56104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
56204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos = buf;
56304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos += snprintf(pos, end - pos, "%s ", m->imsi);
56404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16);
56504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		*pos++ = ' ';
56604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16);
56704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		*pos++ = ' ';
56804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2);
56904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		*pos++ = ' ';
57004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6);
57104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		*pos++ = '\n';
57204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
57304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	no_update:
57404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		fprintf(f2, "%s", buf);
57504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
57604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
57704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	fclose(f2);
57804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	fclose(f);
57904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
58004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	snprintf(buf, sizeof(buf), "%s.bak", fname);
58104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (rename(fname, buf) < 0) {
58204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		perror("rename");
58304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
58404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
58504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
58604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	snprintf(buf, sizeof(buf), "%s.new", fname);
58704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (rename(buf, fname) < 0) {
58804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		perror("rename");
58904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
59004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
59104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
59204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
59304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
59404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct milenage_parameters * get_milenage(const char *imsi)
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct milenage_parameters *m = milenage_db;
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (m) {
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strcmp(m->imsi, imsi) == 0)
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m = m->next;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
60561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
60661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!m)
60761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		m = db_get_milenage(imsi);
60861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
60961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return m;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 char *imsi)
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count, max_chal, ret;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char reply[1000], *rpos, *rend;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct milenage_parameters *m;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct gsm_triplet *g;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reply[0] = '\0';
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = strchr(imsi, ' ');
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos) {
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = '\0';
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		max_chal = atoi(pos);
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL)
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			max_chal = EAP_SIM_MAX_CHAL;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		max_chal = EAP_SIM_MAX_CHAL;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rend = &reply[sizeof(reply)];
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rpos = reply;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || ret >= rend - rpos)
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rpos += ret;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = get_milenage(imsi);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m) {
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 _rand[16], sres[4], kc[8];
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (count = 0; count < max_chal; count++) {
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (random_get_bytes(_rand, 16) < 0)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gsm_milenage(m->opc, m->ki, _rand, sres, kc);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*rpos++ = ' ';
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*rpos++ = ':';
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*rpos++ = ':';
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*rpos = '\0';
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto send;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = 0;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (count < max_chal && (g = get_gsm_triplet(imsi))) {
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strcmp(g->imsi, imsi) != 0)
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rpos < rend)
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*rpos++ = ' ';
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8);
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rpos < rend)
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*rpos++ = ':';
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4);
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rpos < rend)
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*rpos++ = ':';
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count == 0) {
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("No GSM triplets found for %s\n", imsi);
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = snprintf(rpos, rend - rpos, " FAILURE");
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || ret >= rend - rpos)
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rpos += ret;
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsend:
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Send: %s\n", reply);
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sendto(s, reply, rpos - reply, 0,
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (struct sockaddr *) from, fromlen) < 0)
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("send");
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
69204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void inc_sqn(u8 *sqn)
69304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
69404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	u64 val, seq, ind;
69504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
69604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	/*
69704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 * SQN = SEQ | IND = SEQ1 | SEQ2 | IND
69804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 *
69904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 * The mechanism used here is not time-based, so SEQ2 is void and
70004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 * SQN = SEQ1 | IND. The length of IND is ind_len bits and the length
70104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 * of SEQ1 is 48 - ind_len bits.
70204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	 */
70304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
70404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	/* Increment both SEQ and IND by one */
70504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	val = ((u64) WPA_GET_BE32(sqn) << 16) | ((u64) WPA_GET_BE16(sqn + 4));
70604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	seq = (val >> ind_len) + 1;
70704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ind = (val + 1) & ((1 << ind_len) - 1);
70804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	val = (seq << ind_len) | ind;
70904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	WPA_PUT_BE32(sqn, val >> 16);
71004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	WPA_PUT_BE16(sqn + 4, val & 0xffff);
71104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
71204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
71304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 char *imsi)
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char reply[1000], *pos, *end;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 _rand[EAP_AKA_RAND_LEN];
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 autn[EAP_AKA_AUTN_LEN];
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 ik[EAP_AKA_IK_LEN];
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 ck[EAP_AKA_CK_LEN];
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 res[EAP_AKA_RES_MAX_LEN];
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t res_len;
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct milenage_parameters *m;
72761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int failed = 0;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = get_milenage(imsi);
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m) {
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res_len = EAP_AKA_RES_MAX_LEN;
73404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		inc_sqn(m->sqn);
73561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
73661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		db_update_milenage_sqn(m);
73761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
73804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sqn_changes = 1;
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       m->sqn[0], m->sqn[1], m->sqn[2],
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       m->sqn[3], m->sqn[4], m->sqn[5]);
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  autn, ik, ck, res, &res_len);
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Unknown IMSI: %s\n", imsi);
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef AKA_USE_FIXED_TEST_VALUES
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Using fixed test values for AKA\n");
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memset(_rand, '0', EAP_AKA_RAND_LEN);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memset(autn, '1', EAP_AKA_AUTN_LEN);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memset(ik, '3', EAP_AKA_IK_LEN);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memset(ck, '4', EAP_AKA_CK_LEN);
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memset(res, '2', EAP_AKA_RES_MAX_LEN);
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res_len = EAP_AKA_RES_MAX_LEN;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* AKA_USE_FIXED_TEST_VALUES */
75561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		failed = 1;
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* AKA_USE_FIXED_TEST_VALUES */
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = reply;
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = &reply[sizeof(reply)];
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || ret >= end - pos)
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += ret;
76561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (failed) {
76661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		ret = snprintf(pos, end - pos, "FAILURE");
76761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (ret < 0 || ret >= end - pos)
76861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return;
76961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pos += ret;
77061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		goto done;
77161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = ' ';
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = ' ';
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN);
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = ' ';
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN);
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = ' ';
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
78261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtdone:
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Send: %s\n", reply);
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   fromlen) < 0)
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("send");
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     char *imsi)
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *auts, *__rand;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct milenage_parameters *m;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* AKA-AUTS <IMSI> <AUTS> <RAND> */
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	auts = strchr(imsi, ' ');
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (auts == NULL)
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*auts++ = '\0';
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	__rand = strchr(auts, ' ');
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (__rand == NULL)
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*__rand++ = '\0';
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand);
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not parse AUTS/RAND\n");
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = get_milenage(imsi);
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (m == NULL) {
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Unknown IMSI: %s\n", imsi);
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("AKA-AUTS: Incorrect MAC-S\n");
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		memcpy(m->sqn, sqn, 6);
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("AKA-AUTS: Re-synchronized: "
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "SQN=%02x%02x%02x%02x%02x%02x\n",
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
83061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
83161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		db_update_milenage_sqn(m);
83261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
83304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sqn_changes = 1;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int process(int s)
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[1000];
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un from;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socklen_t fromlen;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssize_t res;
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fromlen = sizeof(from);
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from,
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       &fromlen);
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("recvfrom");
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0)
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((size_t) res >= sizeof(buf))
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = sizeof(buf) - 1;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[res] = '\0';
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Received: %s\n", buf);
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sim_req_auth(s, &from, fromlen, buf + 13);
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		aka_req_auth(s, &from, fromlen, buf + 13);
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		aka_auts(s, &from, fromlen, buf + 9);
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Unknown request: %s\n", buf);
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void cleanup(void)
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct gsm_triplet *g, *gprev;
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct milenage_parameters *m, *prev;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
88004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (update_milenage && milenage_file && sqn_changes)
88104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		update_milenage_file(milenage_file);
88204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	g = gsm_db;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (g) {
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gprev = g;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		g = g->next;
88704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_free(gprev);
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = milenage_db;
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (m) {
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = m;
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		m = m->next;
89404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		os_free(prev);
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	close(serv_sock);
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unlink(socket_path);
89961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
90061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
90161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sqlite_db) {
90261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sqlite3_close(sqlite_db);
90361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sqlite_db = NULL;
90461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
90561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_term(int sig)
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Signal %d - terminate\n", sig);
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	exit(0);
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "database/authenticator\n"
92004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	       "Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>\n"
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "\n"
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "usage:\n"
92304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	       "hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
92404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	       "[-m<milenage file>] \\\n"
92561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	       "        [-D<DB file>] [-i<IND len in bits>]\n"
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "\n"
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "options:\n"
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -h = show this usage help\n"
92904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	       "  -u = update SQN in Milenage file on exit\n"
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -s<socket path> = path for UNIX domain socket\n"
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                    (default: %s)\n"
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -g<triplet file> = path for GSM authentication triplets\n"
93304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	       "  -m<milenage file> = path for Milenage keys\n"
93461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	       "  -D<DB file> = path to SQLite database\n"
93504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	       "  -i<IND len in bits> = IND length for SQN (default: 5)\n",
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       default_socket_path);
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c;
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *gsm_triplet_file = NULL;
94461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *sqlite_db_file = NULL;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
94604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (os_program_init())
94704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
94804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	socket_path = default_socket_path;
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
95261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		c = getopt(argc, argv, "D:g:hi:m:s:u");
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
95661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		case 'D':
95761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
95861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			sqlite_db_file = optarg;
95961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
96061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#else /* CONFIG_SQLITE */
96161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			printf("No SQLite support included in the build\n");
96261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
96361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'g':
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gsm_triplet_file = optarg;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'h':
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
97004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		case 'i':
97104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			ind_len = atoi(optarg);
97204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (ind_len < 0 || ind_len > 32) {
97304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				printf("Invalid IND length\n");
97404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				return -1;
97504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			}
97604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'm':
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			milenage_file = optarg;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 's':
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			socket_path = optarg;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
98304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		case 'u':
98404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			update_milenage = 1;
98504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
99261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!gsm_triplet_file && !milenage_file && !sqlite_db_file) {
99361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage();
99461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
99561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
99661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
99761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
99861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sqlite_db_file && (sqlite_db = db_open(sqlite_db_file)) == NULL)
99961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
100061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
100161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (milenage_file && read_milenage(milenage_file) < 0)
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	serv_sock = open_socket(socket_path);
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (serv_sock < 0)
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Listening for requests on %s\n", socket_path);
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	atexit(cleanup);
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	signal(SIGTERM, handle_term);
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	signal(SIGINT, handle_term);
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;)
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		process(serv_sock);
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
102161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE
102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sqlite_db) {
102361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sqlite3_close(sqlite_db);
102461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sqlite_db = NULL;
102561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
102661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */
102761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
102804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_program_deinit();
102904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1032