18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator 3293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt * Copyright (c) 2005-2007, 2012-2017, 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 21051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * GSM-AUTH-REQ <IMSI> RAND1:RAND2[:RAND3] 22051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * GSM-AUTH-RESP <IMSI> Kc1:SRES1:Kc2:SRES2[:Kc3:SRES3] 23051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * GSM-AUTH-RESP <IMSI> FAILURE 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-AKA / UMTS query/response: 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-REQ-AUTH <IMSI> 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-RESP-AUTH <IMSI> FAILURE 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-AKA / UMTS AUTS (re-synchronization): 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AKA-AUTS <IMSI> <AUTS> <RAND> 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IMSI and max_chal are sent as an ASCII string, 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings. 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 365605286c30e1701491bd3af974ae423727750eddDmitry Shmidt * An example implementation here reads GSM authentication triplets from a 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * strings. This is used to simulate an HLR/AuC. As such, it is not very useful 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for real life authentication, but it is useful both as an example 4004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * implementation and for EAP-SIM/AKA/AKA' testing. 4104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 425605286c30e1701491bd3af974ae423727750eddDmitry Shmidt * For a stronger example design, Milenage and GSM-Milenage algorithms can be 435605286c30e1701491bd3af974ae423727750eddDmitry Shmidt * used to dynamically generate authenticatipn information for EAP-AKA/AKA' and 445605286c30e1701491bd3af974ae423727750eddDmitry Shmidt * EAP-SIM, respectively, if Ki is known. 455605286c30e1701491bd3af974ae423727750eddDmitry Shmidt * 4604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * SQN generation follows the not time-based Profile 2 described in 4704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this 4804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * can be changed with a command line options if needed. 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/un.h> 5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include <sqlite3.h> 5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/milenage.h" 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *default_socket_path = "/tmp/hlr_auc_gw.sock"; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *socket_path; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int serv_sock = -1; 6404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic char *milenage_file = NULL; 6504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int update_milenage = 0; 6604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int sqn_changes = 0; 6704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int ind_len = 5; 685605286c30e1701491bd3af974ae423727750eddDmitry Shmidtstatic int stdout_debug = 1; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* GSM triplets */ 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct gsm_triplet { 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct gsm_triplet *next; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char imsi[20]; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 kc[8]; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 sres[4]; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 _rand[16]; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct milenage_parameters { 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct milenage_parameters *next; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char imsi[20]; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ki[16]; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 opc[16]; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 amf[2]; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 sqn[6]; 894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int set; 90af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt size_t res_len; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct milenage_parameters *milenage_db = NULL; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_SIM_MAX_CHAL 3 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_RAND_LEN 16 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_AUTN_LEN 16 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_AUTS_LEN 14 100af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt#define EAP_AKA_RES_MIN_LEN 4 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_RES_MAX_LEN 16 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_IK_LEN 16 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_AKA_CK_LEN 16 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic sqlite3 *sqlite_db = NULL; 10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct milenage_parameters db_tmp_milenage; 11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int db_table_exists(sqlite3 *db, const char *name) 11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char cmd[128]; 11561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name); 11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK; 11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 12061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int db_table_create_milenage(sqlite3 *db) 12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *err = NULL; 12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const char *sql = 12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "CREATE TABLE milenage(" 12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " imsi INTEGER PRIMARY KEY NOT NULL," 12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " ki CHAR(32) NOT NULL," 12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " opc CHAR(32) NOT NULL," 12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " amf CHAR(4) NOT NULL," 129af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt " sqn CHAR(12) NOT NULL," 130af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt " res_len INTEGER" 13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ");"; 13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("Adding database table for milenage information\n"); 13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) { 13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("SQLite error: %s\n", err); 13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite3_free(err); 13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 14461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic sqlite3 * db_open(const char *db_file) 14561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 14661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite3 *db; 14761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 14861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sqlite3_open(db_file, &db)) { 14961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("Failed to open database %s: %s\n", 15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt db_file, sqlite3_errmsg(db)); 15161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite3_close(db); 15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 15461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 15561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!db_table_exists(db, "milenage") && 15661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt db_table_create_milenage(db) < 0) { 15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite3_close(db); 15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return db; 16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 16361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 16461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 16561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[]) 16661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 16761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct milenage_parameters *m = ctx; 16861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int i; 16961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt m->set = 1; 1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 17261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < argc; i++) { 17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (os_strcmp(col[i], "ki") == 0 && argv[i] && 17461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hexstr2bin(argv[i], m->ki, sizeof(m->ki))) { 17561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("Invalid ki value in database\n"); 17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (os_strcmp(col[i], "opc") == 0 && argv[i] && 18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hexstr2bin(argv[i], m->opc, sizeof(m->opc))) { 18161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("Invalid opcvalue in database\n"); 18261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (os_strcmp(col[i], "amf") == 0 && argv[i] && 18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hexstr2bin(argv[i], m->amf, sizeof(m->amf))) { 18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("Invalid amf value in database\n"); 18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (os_strcmp(col[i], "sqn") == 0 && argv[i] && 19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hexstr2bin(argv[i], m->sqn, sizeof(m->sqn))) { 19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("Invalid sqn value in database\n"); 19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 19561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 196af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt 197af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt if (os_strcmp(col[i], "res_len") == 0 && argv[i]) { 198af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt m->res_len = atoi(argv[i]); 199af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt } 20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct milenage_parameters * db_get_milenage(const char *imsi_txt) 20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 20861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char cmd[128]; 20961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unsigned long long imsi; 21061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 21161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memset(&db_tmp_milenage, 0, sizeof(db_tmp_milenage)); 21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt imsi = atoll(imsi_txt); 21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi), 21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "%llu", imsi); 21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(cmd, sizeof(cmd), 216af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt "SELECT * FROM milenage WHERE imsi=%llu;", imsi); 21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage, 21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt NULL) != SQLITE_OK) 21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 22061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!db_tmp_milenage.set) 2224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; 22361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return &db_tmp_milenage; 22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int db_update_milenage_sqn(struct milenage_parameters *m) 22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char cmd[128], val[13], *pos; 23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2315605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (sqlite_db == NULL) 2325605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return 0; 2335605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 23461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = val; 23561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6); 23661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *pos = '\0'; 23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(cmd, sizeof(cmd), 23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "UPDATE milenage SET sqn='%s' WHERE imsi=%s;", 23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt val, m->imsi); 24061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sqlite3_exec(sqlite_db, cmd, NULL, NULL, NULL) != SQLITE_OK) { 24161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("Failed to update SQN in database for IMSI %s\n", 24261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt m->imsi); 24361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 24461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 24561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 25061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int open_socket(const char *path) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un addr; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int s; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = socket(PF_UNIX, SOCK_DGRAM, 0); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s < 0) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket(PF_UNIX)"); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(&addr, 0, sizeof(addr)); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sun_family = AF_UNIX; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 26604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt perror("hlr-auc-gw: bind(PF_UNIX)"); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(s); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return s; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int read_gsm_triplets(const char *fname) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FILE *f; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[200], *pos, *pos2; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct gsm_triplet *g = NULL; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int line, ret = 0; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fname == NULL) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f = fopen(fname, "r"); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (f == NULL) { 2877d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("Could not open GSM triplet data file '%s'\n", fname); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt line = 0; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (fgets(buf, sizeof(buf), f)) { 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt line++; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse IMSI:Kc:SRES:RAND */ 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf[0] == '#') 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0' && *pos != '\n') 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\n') 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\0') 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g = os_zalloc(sizeof(*g)); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (g == NULL) { 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IMSI */ 3157d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos2 = NULL; 3167d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, ":", &pos2); 3177d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) >= sizeof(g->imsi)) { 3187d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid IMSI\n", fname, line); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(g->imsi, pos, sizeof(g->imsi)); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Kc */ 3257d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, ":", &pos2); 3267d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) { 3277d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid Kc\n", fname, line); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SRES */ 3337d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, ":", &pos2); 3347d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) != 8 || 3357d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt hexstr2bin(pos, g->sres, 4)) { 3367d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid SRES\n", fname, line); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RAND */ 3427d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, ":", &pos2); 3437d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) != 32 || 3447d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt hexstr2bin(pos, g->_rand, 16)) { 3457d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid RAND\n", fname, line); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g->next = gsm_db; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gsm_db = g; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g = NULL; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(g); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fclose(f); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct gsm_triplet * get_gsm_triplet(const char *imsi) 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct gsm_triplet *g = gsm_db_pos; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (g) { 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (strcmp(g->imsi, imsi) == 0) { 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gsm_db_pos = g->next; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return g; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g = g->next; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g = gsm_db; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (g && g != gsm_db_pos) { 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 return NULL; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int read_milenage(const char *fname) 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FILE *f; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[200], *pos, *pos2; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct milenage_parameters *m = NULL; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int line, ret = 0; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fname == NULL) 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f = fopen(fname, "r"); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (f == NULL) { 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not open Milenage data file '%s'\n", fname); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt line = 0; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (fgets(buf, sizeof(buf), f)) { 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt line++; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 407af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt /* Parse IMSI Ki OPc AMF SQN [RES_len] */ 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf[0] == '#') 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0' && *pos != '\n') 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\n') 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\0') 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = os_zalloc(sizeof(*m)); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m == NULL) { 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IMSI */ 4277d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos2 = NULL; 4287d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, " ", &pos2); 4297d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) >= sizeof(m->imsi)) { 4307d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid IMSI\n", fname, line); 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(m->imsi, pos, sizeof(m->imsi)); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ki */ 4377d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, " ", &pos2); 4387d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) != 32 || 4397d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt hexstr2bin(pos, m->ki, 16)) { 4407d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid Ki\n", fname, line); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* OPc */ 4467d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, " ", &pos2); 4477d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) != 32 || 4487d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt hexstr2bin(pos, m->opc, 16)) { 4497d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid OPc\n", fname, line); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AMF */ 4557d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, " ", &pos2); 4567d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) { 4577d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid AMF\n", fname, line); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SQN */ 4637d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, " ", &pos2); 4647d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (!pos || os_strlen(pos) != 12 || 4657d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt hexstr2bin(pos, m->sqn, 6)) { 4667d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid SEQ\n", fname, line); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 470af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt 4717d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt pos = str_token(buf, " ", &pos2); 4727d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt if (pos) { 473af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt m->res_len = atoi(pos); 474af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt if (m->res_len && 475af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt (m->res_len < EAP_AKA_RES_MIN_LEN || 476af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt m->res_len > EAP_AKA_RES_MAX_LEN)) { 4777d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt printf("%s:%d - Invalid RES_len\n", 4787d56b75791f317618c9c3ff08a4cfc36c91c9611Dmitry Shmidt fname, line); 479af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt ret = -1; 480af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt break; 481af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt } 482af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt } 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m->next = milenage_db; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt milenage_db = m; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = NULL; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(m); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fclose(f); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void update_milenage_file(const char *fname) 49704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 49804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt FILE *f, *f2; 499d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt char name[500], buf[500], *pos; 50004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *end = buf + sizeof(buf); 50104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct milenage_parameters *m; 50204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t imsi_len; 50304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 50404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt f = fopen(fname, "r"); 50504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (f == NULL) { 50604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt printf("Could not open Milenage data file '%s'\n", fname); 50704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 50804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 50904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 510d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt snprintf(name, sizeof(name), "%s.new", fname); 511d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt f2 = fopen(name, "w"); 51204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (f2 == NULL) { 513d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt printf("Could not write Milenage data file '%s'\n", name); 51404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt fclose(f); 51504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 51604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 51704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 51804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (fgets(buf, sizeof(buf), f)) { 51904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* IMSI Ki OPc AMF SQN */ 52004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 52104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 52204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = strchr(buf, ' '); 52304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (buf[0] == '#' || pos == NULL || pos - buf >= 20) 52404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto no_update; 52504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 52604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt imsi_len = pos - buf; 52704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 52804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (m = milenage_db; m; m = m->next) { 52904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (strncmp(buf, m->imsi, imsi_len) == 0 && 53004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt m->imsi[imsi_len] == '\0') 53104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 53204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 53304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 53404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!m) 53504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto no_update; 53604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 53704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = buf; 53804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += snprintf(pos, end - pos, "%s ", m->imsi); 53904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16); 54004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = ' '; 54104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16); 54204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = ' '; 54304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2); 54404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = ' '; 54504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6); 54604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = '\n'; 54704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 54804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt no_update: 54904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt fprintf(f2, "%s", buf); 55004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 55104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 55204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt fclose(f2); 55304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt fclose(f); 55404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 555d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt snprintf(name, sizeof(name), "%s.bak", fname); 556d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (rename(fname, name) < 0) { 55704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt perror("rename"); 55804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 55904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 56004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 561d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt snprintf(name, sizeof(name), "%s.new", fname); 562d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (rename(name, fname) < 0) { 56304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt perror("rename"); 56404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 56504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 56604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 56704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 56804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 56904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct milenage_parameters * get_milenage(const char *imsi) 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct milenage_parameters *m = milenage_db; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (m) { 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (strcmp(m->imsi, imsi) == 0) 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = m->next; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 58161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!m) 58261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt m = db_get_milenage(imsi); 58361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 58461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return m; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5895605286c30e1701491bd3af974ae423727750eddDmitry Shmidtstatic int sim_req_auth(char *imsi, char *resp, size_t resp_len) 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count, max_chal, ret; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos; 5935605286c30e1701491bd3af974ae423727750eddDmitry Shmidt char *rpos, *rend; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct milenage_parameters *m; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct gsm_triplet *g; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5975605286c30e1701491bd3af974ae423727750eddDmitry Shmidt resp[0] = '\0'; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = strchr(imsi, ' '); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) { 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = '\0'; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_chal = atoi(pos); 6035605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (max_chal < 1 || max_chal > EAP_SIM_MAX_CHAL) 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_chal = EAP_SIM_MAX_CHAL; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_chal = EAP_SIM_MAX_CHAL; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6085605286c30e1701491bd3af974ae423727750eddDmitry Shmidt rend = resp + resp_len; 6095605286c30e1701491bd3af974ae423727750eddDmitry Shmidt rpos = resp; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= rend - rpos) 6125605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += ret; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = get_milenage(imsi); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m) { 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 _rand[16], sres[4], kc[8]; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (count = 0; count < max_chal; count++) { 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(_rand, 16) < 0) 6205605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gsm_milenage(m->opc, m->ki, _rand, sres, kc); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = ' '; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = ':'; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = ':'; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos = '\0'; 6305605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return 0; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (count < max_chal && (g = get_gsm_triplet(imsi))) { 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (strcmp(g->imsi, imsi) != 0) 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos < rend) 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = ' '; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos < rend) 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = ':'; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos < rend) 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = ':'; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0) { 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("No GSM triplets found for %s\n", imsi); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = snprintf(rpos, rend - rpos, " FAILURE"); 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= rend - rpos) 6545605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += ret; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6585605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return 0; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 662051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int gsm_auth_req(char *imsi, char *resp, size_t resp_len) 663051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 664051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int count, ret; 665051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt char *pos, *rpos, *rend; 666051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct milenage_parameters *m; 667051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 668051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt resp[0] = '\0'; 669051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 670051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos = os_strchr(imsi, ' '); 671051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (!pos) 672051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 673051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *pos++ = '\0'; 674051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 675051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt rend = resp + resp_len; 676051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt rpos = resp; 677051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt ret = os_snprintf(rpos, rend - rpos, "GSM-AUTH-RESP %s", imsi); 6786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(rend - rpos, ret)) 679051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 680051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt rpos += ret; 681051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 682051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt m = get_milenage(imsi); 683051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (m) { 684051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt u8 _rand[16], sres[4], kc[8]; 685051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (count = 0; count < EAP_SIM_MAX_CHAL; count++) { 686051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (hexstr2bin(pos, _rand, 16) != 0) 687051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 688051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt gsm_milenage(m->opc, m->ki, _rand, sres, kc); 689051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *rpos++ = count == 0 ? ' ' : ':'; 690051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8); 691051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *rpos++ = ':'; 692051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4); 693051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += 16 * 2; 694051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (*pos != ':') 695051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 696051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos++; 697051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 698051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *rpos = '\0'; 699051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 700051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 701051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 702051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt printf("No GSM triplets found for %s\n", imsi); 703051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt ret = os_snprintf(rpos, rend - rpos, " FAILURE"); 7046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(rend - rpos, ret)) 705051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 706051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt rpos += ret; 707051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 708051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 709051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 710051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 711051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 71204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void inc_sqn(u8 *sqn) 71304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 71404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u64 val, seq, ind; 71504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 71604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 71704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * SQN = SEQ | IND = SEQ1 | SEQ2 | IND 71804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 71904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * The mechanism used here is not time-based, so SEQ2 is void and 72004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * SQN = SEQ1 | IND. The length of IND is ind_len bits and the length 72104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * of SEQ1 is 48 - ind_len bits. 72204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 72304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 72404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Increment both SEQ and IND by one */ 72504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val = ((u64) WPA_GET_BE32(sqn) << 16) | ((u64) WPA_GET_BE16(sqn + 4)); 72604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt seq = (val >> ind_len) + 1; 72704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ind = (val + 1) & ((1 << ind_len) - 1); 72804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt val = (seq << ind_len) | ind; 72904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WPA_PUT_BE32(sqn, val >> 16); 73004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WPA_PUT_BE16(sqn + 4, val & 0xffff); 73104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 73204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 73304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 7345605286c30e1701491bd3af974ae423727750eddDmitry Shmidtstatic int aka_req_auth(char *imsi, char *resp, size_t resp_len) 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */ 7375605286c30e1701491bd3af974ae423727750eddDmitry Shmidt char *pos, *end; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 _rand[EAP_AKA_RAND_LEN]; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 autn[EAP_AKA_AUTN_LEN]; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ik[EAP_AKA_IK_LEN]; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ck[EAP_AKA_CK_LEN]; 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 res[EAP_AKA_RES_MAX_LEN]; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t res_len; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct milenage_parameters *m; 74661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int failed = 0; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = get_milenage(imsi); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m) { 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0) 7515605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_len = EAP_AKA_RES_MAX_LEN; 75304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt inc_sqn(m->sqn); 75461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 75561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt db_update_milenage_sqn(m); 75661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 75704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sqn_changes = 1; 7585605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (stdout_debug) { 7595605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n", 7605605286c30e1701491bd3af974ae423727750eddDmitry Shmidt m->sqn[0], m->sqn[1], m->sqn[2], 7615605286c30e1701491bd3af974ae423727750eddDmitry Shmidt m->sqn[3], m->sqn[4], m->sqn[5]); 7625605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand, 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt autn, ik, ck, res, &res_len); 765af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt if (m->res_len >= EAP_AKA_RES_MIN_LEN && 766af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt m->res_len <= EAP_AKA_RES_MAX_LEN && 767af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt m->res_len < res_len) 768af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt res_len = m->res_len; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Unknown IMSI: %s\n", imsi); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef AKA_USE_FIXED_TEST_VALUES 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Using fixed test values for AKA\n"); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(_rand, '0', EAP_AKA_RAND_LEN); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(autn, '1', EAP_AKA_AUTN_LEN); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(ik, '3', EAP_AKA_IK_LEN); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(ck, '4', EAP_AKA_CK_LEN); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(res, '2', EAP_AKA_RES_MAX_LEN); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res_len = EAP_AKA_RES_MAX_LEN; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* AKA_USE_FIXED_TEST_VALUES */ 78061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt failed = 1; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* AKA_USE_FIXED_TEST_VALUES */ 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7845605286c30e1701491bd3af974ae423727750eddDmitry Shmidt pos = resp; 7855605286c30e1701491bd3af974ae423727750eddDmitry Shmidt end = resp + resp_len; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi); 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) 7885605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 79061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (failed) { 79161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ret = snprintf(pos, end - pos, "FAILURE"); 79261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ret < 0 || ret >= end - pos) 7935605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 79461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += ret; 7955605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return 0; 79661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN); 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = ' '; 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = ' '; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = ' '; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN); 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = ' '; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, res, res_len); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8075605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return 0; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8115605286c30e1701491bd3af974ae423727750eddDmitry Shmidtstatic int aka_auts(char *imsi, char *resp, size_t resp_len) 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *auts, *__rand; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6]; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct milenage_parameters *m; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8175605286c30e1701491bd3af974ae423727750eddDmitry Shmidt resp[0] = '\0'; 8185605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AKA-AUTS <IMSI> <AUTS> <RAND> */ 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auts = strchr(imsi, ' '); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auts == NULL) 8235605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *auts++ = '\0'; 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __rand = strchr(auts, ' '); 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (__rand == NULL) 8285605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *__rand++ = '\0'; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8315605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (stdout_debug) { 8325605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", 8335605286c30e1701491bd3af974ae423727750eddDmitry Shmidt imsi, auts, __rand); 8345605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) || 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) { 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not parse AUTS/RAND\n"); 8385605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = get_milenage(imsi); 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m == NULL) { 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Unknown IMSI: %s\n", imsi); 8445605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) { 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("AKA-AUTS: Incorrect MAC-S\n"); 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(m->sqn, sqn, 6); 8515605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (stdout_debug) { 8525605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("AKA-AUTS: Re-synchronized: " 8535605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "SQN=%02x%02x%02x%02x%02x%02x\n", 8545605286c30e1701491bd3af974ae423727750eddDmitry Shmidt sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]); 8555605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 85661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 85761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt db_update_milenage_sqn(m); 85861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 85904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sqn_changes = 1; 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8615605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 8625605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return 0; 8635605286c30e1701491bd3af974ae423727750eddDmitry Shmidt} 8645605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 8655605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 8665605286c30e1701491bd3af974ae423727750eddDmitry Shmidtstatic int process_cmd(char *cmd, char *resp, size_t resp_len) 8675605286c30e1701491bd3af974ae423727750eddDmitry Shmidt{ 8685605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (os_strncmp(cmd, "SIM-REQ-AUTH ", 13) == 0) 8695605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return sim_req_auth(cmd + 13, resp, resp_len); 8705605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 871051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (os_strncmp(cmd, "GSM-AUTH-REQ ", 13) == 0) 872051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return gsm_auth_req(cmd + 13, resp, resp_len); 873051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 8745605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (os_strncmp(cmd, "AKA-REQ-AUTH ", 13) == 0) 8755605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return aka_req_auth(cmd + 13, resp, resp_len); 8765605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 8775605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (os_strncmp(cmd, "AKA-AUTS ", 9) == 0) 8785605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return aka_auts(cmd + 9, resp, resp_len); 8795605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 8805605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("Unknown request: %s\n", cmd); 8815605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int process(int s) 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8875605286c30e1701491bd3af974ae423727750eddDmitry Shmidt char buf[1000], resp[1000]; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_un from; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen; 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t res; 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen = sizeof(from); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from, 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &fromlen); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("recvfrom"); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((size_t) res >= sizeof(buf)) 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = sizeof(buf) - 1; 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[res] = '\0'; 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Received: %s\n", buf); 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9095605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (process_cmd(buf, resp, sizeof(resp)) < 0) { 9105605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("Failed to process request\n"); 9115605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 9125605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 9135605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 9145605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (resp[0] == '\0') { 9155605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("No response\n"); 9165605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return 0; 9175605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 9185605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 9195605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("Send: %s\n", resp); 9205605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 9215605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (sendto(s, resp, os_strlen(resp), 0, (struct sockaddr *) &from, 9225605286c30e1701491bd3af974ae423727750eddDmitry Shmidt fromlen) < 0) 9235605286c30e1701491bd3af974ae423727750eddDmitry Shmidt perror("send"); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void cleanup(void) 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct gsm_triplet *g, *gprev; 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct milenage_parameters *m, *prev; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 93404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (update_milenage && milenage_file && sqn_changes) 93504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt update_milenage_file(milenage_file); 93604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g = gsm_db; 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (g) { 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gprev = g; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt g = g->next; 94104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(gprev); 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = milenage_db; 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (m) { 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = m; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m = m->next; 94804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(prev); 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9515605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (serv_sock >= 0) 9525605286c30e1701491bd3af974ae423727750eddDmitry Shmidt close(serv_sock); 9535605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (socket_path) 9545605286c30e1701491bd3af974ae423727750eddDmitry Shmidt unlink(socket_path); 95561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 95661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 95761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sqlite_db) { 95861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite3_close(sqlite_db); 95961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite_db = NULL; 96061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 96161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_term(int sig) 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Signal %d - terminate\n", sig); 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt exit(0); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void) 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA " 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "database/authenticator\n" 976293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt "Copyright (c) 2005-2017, Jouni Malinen <j@w1.fi>\n" 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\n" 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "usage:\n" 97904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] " 98004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "[-m<milenage file>] \\\n" 9815605286c30e1701491bd3af974ae423727750eddDmitry Shmidt " [-D<DB file>] [-i<IND len in bits>] [command]\n" 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\n" 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "options:\n" 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -h = show this usage help\n" 98504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt " -u = update SQN in Milenage file on exit\n" 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -s<socket path> = path for UNIX domain socket\n" 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (default: %s)\n" 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " -g<triplet file> = path for GSM authentication triplets\n" 98904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt " -m<milenage file> = path for Milenage keys\n" 99061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " -D<DB file> = path to SQLite database\n" 9915605286c30e1701491bd3af974ae423727750eddDmitry Shmidt " -i<IND len in bits> = IND length for SQN (default: 5)\n" 9925605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "\n" 9935605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "If the optional command argument, like " 9945605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "\"AKA-REQ-AUTH <IMSI>\" is used, a single\n" 9955605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "command is processed with response sent to stdout. Otherwise, " 9965605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "hlr_auc_gw opens\n" 9975605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "a control interface and processes commands sent through it " 9985605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "(e.g., by EAP server\n" 9995605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "in hostapd).\n", 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default_socket_path); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[]) 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int c; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *gsm_triplet_file = NULL; 100861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *sqlite_db_file = NULL; 10095605286c30e1701491bd3af974ae423727750eddDmitry Shmidt int ret = 0; 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 101104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (os_program_init()) 101204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 101304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socket_path = default_socket_path; 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 101761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt c = getopt(argc, argv, "D:g:hi:m:s:u"); 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (c < 0) 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (c) { 102161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case 'D': 102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 102361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite_db_file = optarg; 102461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 102561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#else /* CONFIG_SQLITE */ 102661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt printf("No SQLite support included in the build\n"); 102761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 102861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'g': 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gsm_triplet_file = optarg; 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'h': 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt usage(); 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 103504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case 'i': 103604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ind_len = atoi(optarg); 103704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ind_len < 0 || ind_len > 32) { 103804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt printf("Invalid IND length\n"); 103904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 104004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 104104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 'm': 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt milenage_file = optarg; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 's': 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socket_path = optarg; 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 104804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case 'u': 104904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt update_milenage = 1; 105004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt usage(); 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 105761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!gsm_triplet_file && !milenage_file && !sqlite_db_file) { 105861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt usage(); 105961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 106061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 106161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 106261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 106361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sqlite_db_file && (sqlite_db = db_open(sqlite_db_file)) == NULL) 106461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 106561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 106661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0) 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (milenage_file && read_milenage(milenage_file) < 0) 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10735605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (optind == argc) { 10745605286c30e1701491bd3af974ae423727750eddDmitry Shmidt serv_sock = open_socket(socket_path); 10755605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (serv_sock < 0) 10765605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return -1; 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10785605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("Listening for requests on %s\n", socket_path); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10805605286c30e1701491bd3af974ae423727750eddDmitry Shmidt atexit(cleanup); 10815605286c30e1701491bd3af974ae423727750eddDmitry Shmidt signal(SIGTERM, handle_term); 10825605286c30e1701491bd3af974ae423727750eddDmitry Shmidt signal(SIGINT, handle_term); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10845605286c30e1701491bd3af974ae423727750eddDmitry Shmidt for (;;) 10855605286c30e1701491bd3af974ae423727750eddDmitry Shmidt process(serv_sock); 10865605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } else { 10875605286c30e1701491bd3af974ae423727750eddDmitry Shmidt char buf[1000]; 10885605286c30e1701491bd3af974ae423727750eddDmitry Shmidt socket_path = NULL; 10895605286c30e1701491bd3af974ae423727750eddDmitry Shmidt stdout_debug = 0; 10905605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (process_cmd(argv[optind], buf, sizeof(buf)) < 0) { 10915605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("FAIL\n"); 10925605286c30e1701491bd3af974ae423727750eddDmitry Shmidt ret = -1; 10935605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } else { 10945605286c30e1701491bd3af974ae423727750eddDmitry Shmidt printf("%s\n", buf); 10955605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 10965605286c30e1701491bd3af974ae423727750eddDmitry Shmidt cleanup(); 10975605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 109961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_SQLITE 110061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sqlite_db) { 110161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite3_close(sqlite_db); 110261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sqlite_db = NULL; 110361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 110461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_SQLITE */ 110561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 110604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_program_deinit(); 110704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 11085605286c30e1701491bd3af974ae423727750eddDmitry Shmidt return ret; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1110