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