LCOV - code coverage report
Current view: top level - hostapd - hlr_auc_gw.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 374 602 62.1 %
Date: 2015-09-27 Functions: 18 23 78.3 %

          Line data    Source code
       1             : /*
       2             :  * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
       3             :  * Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  *
       8             :  * This is an example implementation of the EAP-SIM/AKA database/authentication
       9             :  * gateway interface to HLR/AuC. It is expected to be replaced with an
      10             :  * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or
      11             :  * a local implementation of SIM triplet and AKA authentication data generator.
      12             :  *
      13             :  * hostapd will send SIM/AKA authentication queries over a UNIX domain socket
      14             :  * to and external program, e.g., this hlr_auc_gw. This interface uses simple
      15             :  * text-based format:
      16             :  *
      17             :  * EAP-SIM / GSM triplet query/response:
      18             :  * SIM-REQ-AUTH <IMSI> <max_chal>
      19             :  * SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3]
      20             :  * SIM-RESP-AUTH <IMSI> FAILURE
      21             :  * GSM-AUTH-REQ <IMSI> RAND1:RAND2[:RAND3]
      22             :  * GSM-AUTH-RESP <IMSI> Kc1:SRES1:Kc2:SRES2[:Kc3:SRES3]
      23             :  * GSM-AUTH-RESP <IMSI> FAILURE
      24             :  *
      25             :  * EAP-AKA / UMTS query/response:
      26             :  * AKA-REQ-AUTH <IMSI>
      27             :  * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
      28             :  * AKA-RESP-AUTH <IMSI> FAILURE
      29             :  *
      30             :  * EAP-AKA / UMTS AUTS (re-synchronization):
      31             :  * AKA-AUTS <IMSI> <AUTS> <RAND>
      32             :  *
      33             :  * IMSI and max_chal are sent as an ASCII string,
      34             :  * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
      35             :  *
      36             :  * An example implementation here reads GSM authentication triplets from a
      37             :  * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
      38             :  * strings. This is used to simulate an HLR/AuC. As such, it is not very useful
      39             :  * for real life authentication, but it is useful both as an example
      40             :  * implementation and for EAP-SIM/AKA/AKA' testing.
      41             :  *
      42             :  * For a stronger example design, Milenage and GSM-Milenage algorithms can be
      43             :  * used to dynamically generate authenticatipn information for EAP-AKA/AKA' and
      44             :  * EAP-SIM, respectively, if Ki is known.
      45             :  *
      46             :  * SQN generation follows the not time-based Profile 2 described in
      47             :  * 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this
      48             :  * can be changed with a command line options if needed.
      49             :  */
      50             : 
      51             : #include "includes.h"
      52             : #include <sys/un.h>
      53             : #ifdef CONFIG_SQLITE
      54             : #include <sqlite3.h>
      55             : #endif /* CONFIG_SQLITE */
      56             : 
      57             : #include "common.h"
      58             : #include "crypto/milenage.h"
      59             : #include "crypto/random.h"
      60             : 
      61             : static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
      62             : static const char *socket_path;
      63             : static int serv_sock = -1;
      64             : static char *milenage_file = NULL;
      65             : static int update_milenage = 0;
      66             : static int sqn_changes = 0;
      67             : static int ind_len = 5;
      68             : static int stdout_debug = 1;
      69             : 
      70             : /* GSM triplets */
      71             : struct gsm_triplet {
      72             :         struct gsm_triplet *next;
      73             :         char imsi[20];
      74             :         u8 kc[8];
      75             :         u8 sres[4];
      76             :         u8 _rand[16];
      77             : };
      78             : 
      79             : static struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL;
      80             : 
      81             : /* OPc and AMF parameters for Milenage (Example algorithms for AKA). */
      82             : struct milenage_parameters {
      83             :         struct milenage_parameters *next;
      84             :         char imsi[20];
      85             :         u8 ki[16];
      86             :         u8 opc[16];
      87             :         u8 amf[2];
      88             :         u8 sqn[6];
      89             :         int set;
      90             :         size_t res_len;
      91             : };
      92             : 
      93             : static struct milenage_parameters *milenage_db = NULL;
      94             : 
      95             : #define EAP_SIM_MAX_CHAL 3
      96             : 
      97             : #define EAP_AKA_RAND_LEN 16
      98             : #define EAP_AKA_AUTN_LEN 16
      99             : #define EAP_AKA_AUTS_LEN 14
     100             : #define EAP_AKA_RES_MIN_LEN 4
     101             : #define EAP_AKA_RES_MAX_LEN 16
     102             : #define EAP_AKA_IK_LEN 16
     103             : #define EAP_AKA_CK_LEN 16
     104             : 
     105             : 
     106             : #ifdef CONFIG_SQLITE
     107             : 
     108             : static sqlite3 *sqlite_db = NULL;
     109             : static struct milenage_parameters db_tmp_milenage;
     110             : 
     111             : 
     112           0 : static int db_table_exists(sqlite3 *db, const char *name)
     113             : {
     114             :         char cmd[128];
     115           0 :         os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
     116           0 :         return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
     117             : }
     118             : 
     119             : 
     120           0 : static int db_table_create_milenage(sqlite3 *db)
     121             : {
     122           0 :         char *err = NULL;
     123           0 :         const char *sql =
     124             :                 "CREATE TABLE milenage("
     125             :                 "  imsi INTEGER PRIMARY KEY NOT NULL,"
     126             :                 "  ki CHAR(32) NOT NULL,"
     127             :                 "  opc CHAR(32) NOT NULL,"
     128             :                 "  amf CHAR(4) NOT NULL,"
     129             :                 "  sqn CHAR(12) NOT NULL,"
     130             :                 "  res_len INTEGER"
     131             :                 ");";
     132             : 
     133           0 :         printf("Adding database table for milenage information\n");
     134           0 :         if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
     135           0 :                 printf("SQLite error: %s\n", err);
     136           0 :                 sqlite3_free(err);
     137           0 :                 return -1;
     138             :         }
     139             : 
     140           0 :         return 0;
     141             : }
     142             : 
     143             : 
     144           0 : static sqlite3 * db_open(const char *db_file)
     145             : {
     146             :         sqlite3 *db;
     147             : 
     148           0 :         if (sqlite3_open(db_file, &db)) {
     149           0 :                 printf("Failed to open database %s: %s\n",
     150             :                        db_file, sqlite3_errmsg(db));
     151           0 :                 sqlite3_close(db);
     152           0 :                 return NULL;
     153             :         }
     154             : 
     155           0 :         if (!db_table_exists(db, "milenage") &&
     156           0 :             db_table_create_milenage(db) < 0) {
     157           0 :                 sqlite3_close(db);
     158           0 :                 return NULL;
     159             :         }
     160             : 
     161           0 :         return db;
     162             : }
     163             : 
     164             : 
     165           0 : static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
     166             : {
     167           0 :         struct milenage_parameters *m = ctx;
     168             :         int i;
     169             : 
     170           0 :         m->set = 1;
     171             : 
     172           0 :         for (i = 0; i < argc; i++) {
     173           0 :                 if (os_strcmp(col[i], "ki") == 0 && argv[i] &&
     174           0 :                     hexstr2bin(argv[i], m->ki, sizeof(m->ki))) {
     175           0 :                         printf("Invalid ki value in database\n");
     176           0 :                         return -1;
     177             :                 }
     178             : 
     179           0 :                 if (os_strcmp(col[i], "opc") == 0 && argv[i] &&
     180           0 :                     hexstr2bin(argv[i], m->opc, sizeof(m->opc))) {
     181           0 :                         printf("Invalid opcvalue in database\n");
     182           0 :                         return -1;
     183             :                 }
     184             : 
     185           0 :                 if (os_strcmp(col[i], "amf") == 0 && argv[i] &&
     186           0 :                     hexstr2bin(argv[i], m->amf, sizeof(m->amf))) {
     187           0 :                         printf("Invalid amf value in database\n");
     188           0 :                         return -1;
     189             :                 }
     190             : 
     191           0 :                 if (os_strcmp(col[i], "sqn") == 0 && argv[i] &&
     192           0 :                     hexstr2bin(argv[i], m->sqn, sizeof(m->sqn))) {
     193           0 :                         printf("Invalid sqn value in database\n");
     194           0 :                         return -1;
     195             :                 }
     196             : 
     197           0 :                 if (os_strcmp(col[i], "res_len") == 0 && argv[i]) {
     198           0 :                         m->res_len = atoi(argv[i]);
     199             :                 }
     200             :         }
     201             : 
     202           0 :         return 0;
     203             : }
     204             : 
     205             : 
     206           2 : static struct milenage_parameters * db_get_milenage(const char *imsi_txt)
     207             : {
     208             :         char cmd[128];
     209             :         unsigned long long imsi;
     210             : 
     211           2 :         os_memset(&db_tmp_milenage, 0, sizeof(db_tmp_milenage));
     212           2 :         imsi = atoll(imsi_txt);
     213           2 :         os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
     214             :                     "%llu", imsi);
     215           2 :         os_snprintf(cmd, sizeof(cmd),
     216             :                     "SELECT * FROM milenage WHERE imsi=%llu;", imsi);
     217           2 :         if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
     218             :                          NULL) != SQLITE_OK)
     219           2 :                 return NULL;
     220             : 
     221           0 :         if (!db_tmp_milenage.set)
     222           0 :                 return NULL;
     223           0 :         return &db_tmp_milenage;
     224             : }
     225             : 
     226             : 
     227          54 : static int db_update_milenage_sqn(struct milenage_parameters *m)
     228             : {
     229             :         char cmd[128], val[13], *pos;
     230             : 
     231          54 :         if (sqlite_db == NULL)
     232          54 :                 return 0;
     233             : 
     234           0 :         pos = val;
     235           0 :         pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
     236           0 :         *pos = '\0';
     237           0 :         os_snprintf(cmd, sizeof(cmd),
     238             :                     "UPDATE milenage SET sqn='%s' WHERE imsi=%s;",
     239           0 :                     val, m->imsi);
     240           0 :         if (sqlite3_exec(sqlite_db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
     241           0 :                 printf("Failed to update SQN in database for IMSI %s\n",
     242           0 :                        m->imsi);
     243           0 :                 return -1;
     244             :         }
     245           0 :         return 0;
     246             : }
     247             : 
     248             : #endif /* CONFIG_SQLITE */
     249             : 
     250             : 
     251           6 : static int open_socket(const char *path)
     252             : {
     253             :         struct sockaddr_un addr;
     254             :         int s;
     255             : 
     256           6 :         s = socket(PF_UNIX, SOCK_DGRAM, 0);
     257           6 :         if (s < 0) {
     258           0 :                 perror("socket(PF_UNIX)");
     259           0 :                 return -1;
     260             :         }
     261             : 
     262           6 :         memset(&addr, 0, sizeof(addr));
     263           6 :         addr.sun_family = AF_UNIX;
     264           6 :         os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
     265           6 :         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
     266           0 :                 perror("hlr-auc-gw: bind(PF_UNIX)");
     267           0 :                 close(s);
     268           0 :                 return -1;
     269             :         }
     270             : 
     271           6 :         return s;
     272             : }
     273             : 
     274             : 
     275           6 : static int read_gsm_triplets(const char *fname)
     276             : {
     277             :         FILE *f;
     278             :         char buf[200], *pos, *pos2;
     279           6 :         struct gsm_triplet *g = NULL;
     280           6 :         int line, ret = 0;
     281             : 
     282           6 :         if (fname == NULL)
     283           0 :                 return -1;
     284             : 
     285           6 :         f = fopen(fname, "r");
     286           6 :         if (f == NULL) {
     287           0 :                 printf("Could not open GSM tripler data file '%s'\n", fname);
     288           0 :                 return -1;
     289             :         }
     290             : 
     291           6 :         line = 0;
     292         114 :         while (fgets(buf, sizeof(buf), f)) {
     293         102 :                 line++;
     294             : 
     295             :                 /* Parse IMSI:Kc:SRES:RAND */
     296         102 :                 buf[sizeof(buf) - 1] = '\0';
     297         102 :                 if (buf[0] == '#')
     298          54 :                         continue;
     299          48 :                 pos = buf;
     300        2760 :                 while (*pos != '\0' && *pos != '\n')
     301        2664 :                         pos++;
     302          48 :                 if (*pos == '\n')
     303          48 :                         *pos = '\0';
     304          48 :                 pos = buf;
     305          48 :                 if (*pos == '\0')
     306          12 :                         continue;
     307             : 
     308          36 :                 g = os_zalloc(sizeof(*g));
     309          36 :                 if (g == NULL) {
     310           0 :                         ret = -1;
     311           0 :                         break;
     312             :                 }
     313             : 
     314             :                 /* IMSI */
     315          36 :                 pos2 = strchr(pos, ':');
     316          36 :                 if (pos2 == NULL) {
     317           0 :                         printf("%s:%d - Invalid IMSI (%s)\n",
     318             :                                fname, line, pos);
     319           0 :                         ret = -1;
     320           0 :                         break;
     321             :                 }
     322          36 :                 *pos2 = '\0';
     323          36 :                 if (strlen(pos) >= sizeof(g->imsi)) {
     324           0 :                         printf("%s:%d - Too long IMSI (%s)\n",
     325             :                                fname, line, pos);
     326           0 :                         ret = -1;
     327           0 :                         break;
     328             :                 }
     329          36 :                 os_strlcpy(g->imsi, pos, sizeof(g->imsi));
     330          36 :                 pos = pos2 + 1;
     331             : 
     332             :                 /* Kc */
     333          36 :                 pos2 = strchr(pos, ':');
     334          36 :                 if (pos2 == NULL) {
     335           0 :                         printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
     336           0 :                         ret = -1;
     337           0 :                         break;
     338             :                 }
     339          36 :                 *pos2 = '\0';
     340          36 :                 if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
     341           0 :                         printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
     342           0 :                         ret = -1;
     343           0 :                         break;
     344             :                 }
     345          36 :                 pos = pos2 + 1;
     346             : 
     347             :                 /* SRES */
     348          36 :                 pos2 = strchr(pos, ':');
     349          36 :                 if (pos2 == NULL) {
     350           0 :                         printf("%s:%d - Invalid SRES (%s)\n", fname, line,
     351             :                                pos);
     352           0 :                         ret = -1;
     353           0 :                         break;
     354             :                 }
     355          36 :                 *pos2 = '\0';
     356          36 :                 if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) {
     357           0 :                         printf("%s:%d - Invalid SRES (%s)\n", fname, line,
     358             :                                pos);
     359           0 :                         ret = -1;
     360           0 :                         break;
     361             :                 }
     362          36 :                 pos = pos2 + 1;
     363             : 
     364             :                 /* RAND */
     365          36 :                 pos2 = strchr(pos, ':');
     366          36 :                 if (pos2)
     367           0 :                         *pos2 = '\0';
     368          36 :                 if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) {
     369           0 :                         printf("%s:%d - Invalid RAND (%s)\n", fname, line,
     370             :                                pos);
     371           0 :                         ret = -1;
     372           0 :                         break;
     373             :                 }
     374          36 :                 pos = pos2 + 1;
     375             : 
     376          36 :                 g->next = gsm_db;
     377          36 :                 gsm_db = g;
     378          36 :                 g = NULL;
     379             :         }
     380           6 :         os_free(g);
     381             : 
     382           6 :         fclose(f);
     383             : 
     384           6 :         return ret;
     385             : }
     386             : 
     387             : 
     388           4 : static struct gsm_triplet * get_gsm_triplet(const char *imsi)
     389             : {
     390           4 :         struct gsm_triplet *g = gsm_db_pos;
     391             : 
     392          11 :         while (g) {
     393           5 :                 if (strcmp(g->imsi, imsi) == 0) {
     394           2 :                         gsm_db_pos = g->next;
     395           2 :                         return g;
     396             :                 }
     397           3 :                 g = g->next;
     398             :         }
     399             : 
     400           2 :         g = gsm_db;
     401           7 :         while (g && g != gsm_db_pos) {
     402           4 :                 if (strcmp(g->imsi, imsi) == 0) {
     403           1 :                         gsm_db_pos = g->next;
     404           1 :                         return g;
     405             :                 }
     406           3 :                 g = g->next;
     407             :         }
     408             : 
     409           1 :         return NULL;
     410             : }
     411             : 
     412             : 
     413           6 : static int read_milenage(const char *fname)
     414             : {
     415             :         FILE *f;
     416             :         char buf[200], *pos, *pos2;
     417           6 :         struct milenage_parameters *m = NULL;
     418           6 :         int line, ret = 0;
     419             : 
     420           6 :         if (fname == NULL)
     421           0 :                 return -1;
     422             : 
     423           6 :         f = fopen(fname, "r");
     424           6 :         if (f == NULL) {
     425           0 :                 printf("Could not open Milenage data file '%s'\n", fname);
     426           0 :                 return -1;
     427             :         }
     428             : 
     429           6 :         line = 0;
     430          90 :         while (fgets(buf, sizeof(buf), f)) {
     431          78 :                 line++;
     432             : 
     433             :                 /* Parse IMSI Ki OPc AMF SQN [RES_len] */
     434          78 :                 buf[sizeof(buf) - 1] = '\0';
     435          78 :                 if (buf[0] == '#')
     436          54 :                         continue;
     437          24 :                 pos = buf;
     438        1236 :                 while (*pos != '\0' && *pos != '\n')
     439        1188 :                         pos++;
     440          24 :                 if (*pos == '\n')
     441          24 :                         *pos = '\0';
     442          24 :                 pos = buf;
     443          24 :                 if (*pos == '\0')
     444          12 :                         continue;
     445             : 
     446          12 :                 m = os_zalloc(sizeof(*m));
     447          12 :                 if (m == NULL) {
     448           0 :                         ret = -1;
     449           0 :                         break;
     450             :                 }
     451             : 
     452             :                 /* IMSI */
     453          12 :                 pos2 = strchr(pos, ' ');
     454          12 :                 if (pos2 == NULL) {
     455           0 :                         printf("%s:%d - Invalid IMSI (%s)\n",
     456             :                                fname, line, pos);
     457           0 :                         ret = -1;
     458           0 :                         break;
     459             :                 }
     460          12 :                 *pos2 = '\0';
     461          12 :                 if (strlen(pos) >= sizeof(m->imsi)) {
     462           0 :                         printf("%s:%d - Too long IMSI (%s)\n",
     463             :                                fname, line, pos);
     464           0 :                         ret = -1;
     465           0 :                         break;
     466             :                 }
     467          12 :                 os_strlcpy(m->imsi, pos, sizeof(m->imsi));
     468          12 :                 pos = pos2 + 1;
     469             : 
     470             :                 /* Ki */
     471          12 :                 pos2 = strchr(pos, ' ');
     472          12 :                 if (pos2 == NULL) {
     473           0 :                         printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
     474           0 :                         ret = -1;
     475           0 :                         break;
     476             :                 }
     477          12 :                 *pos2 = '\0';
     478          12 :                 if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) {
     479           0 :                         printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
     480           0 :                         ret = -1;
     481           0 :                         break;
     482             :                 }
     483          12 :                 pos = pos2 + 1;
     484             : 
     485             :                 /* OPc */
     486          12 :                 pos2 = strchr(pos, ' ');
     487          12 :                 if (pos2 == NULL) {
     488           0 :                         printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
     489           0 :                         ret = -1;
     490           0 :                         break;
     491             :                 }
     492          12 :                 *pos2 = '\0';
     493          12 :                 if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) {
     494           0 :                         printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
     495           0 :                         ret = -1;
     496           0 :                         break;
     497             :                 }
     498          12 :                 pos = pos2 + 1;
     499             : 
     500             :                 /* AMF */
     501          12 :                 pos2 = strchr(pos, ' ');
     502          12 :                 if (pos2 == NULL) {
     503           0 :                         printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
     504           0 :                         ret = -1;
     505           0 :                         break;
     506             :                 }
     507          12 :                 *pos2 = '\0';
     508          12 :                 if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
     509           0 :                         printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
     510           0 :                         ret = -1;
     511           0 :                         break;
     512             :                 }
     513          12 :                 pos = pos2 + 1;
     514             : 
     515             :                 /* SQN */
     516          12 :                 pos2 = strchr(pos, ' ');
     517          12 :                 if (pos2)
     518           0 :                         *pos2 = '\0';
     519          12 :                 if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) {
     520           0 :                         printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
     521           0 :                         ret = -1;
     522           0 :                         break;
     523             :                 }
     524             : 
     525          12 :                 if (pos2) {
     526           0 :                         pos = pos2 + 1;
     527           0 :                         m->res_len = atoi(pos);
     528           0 :                         if (m->res_len &&
     529           0 :                             (m->res_len < EAP_AKA_RES_MIN_LEN ||
     530           0 :                              m->res_len > EAP_AKA_RES_MAX_LEN)) {
     531           0 :                                 printf("%s:%d - Invalid RES_len (%s)\n",
     532             :                                        fname, line, pos);
     533           0 :                                 ret = -1;
     534           0 :                                 break;
     535             :                         }
     536             :                 }
     537             : 
     538          12 :                 m->next = milenage_db;
     539          12 :                 milenage_db = m;
     540          12 :                 m = NULL;
     541             :         }
     542           6 :         os_free(m);
     543             : 
     544           6 :         fclose(f);
     545             : 
     546           6 :         return ret;
     547             : }
     548             : 
     549             : 
     550           5 : static void update_milenage_file(const char *fname)
     551             : {
     552             :         FILE *f, *f2;
     553             :         char name[500], buf[500], *pos;
     554           5 :         char *end = buf + sizeof(buf);
     555             :         struct milenage_parameters *m;
     556             :         size_t imsi_len;
     557             : 
     558           5 :         f = fopen(fname, "r");
     559           5 :         if (f == NULL) {
     560           0 :                 printf("Could not open Milenage data file '%s'\n", fname);
     561           0 :                 return;
     562             :         }
     563             : 
     564           5 :         snprintf(name, sizeof(name), "%s.new", fname);
     565           5 :         f2 = fopen(name, "w");
     566           5 :         if (f2 == NULL) {
     567           0 :                 printf("Could not write Milenage data file '%s'\n", name);
     568           0 :                 fclose(f);
     569           0 :                 return;
     570             :         }
     571             : 
     572          75 :         while (fgets(buf, sizeof(buf), f)) {
     573             :                 /* IMSI Ki OPc AMF SQN */
     574          65 :                 buf[sizeof(buf) - 1] = '\0';
     575             : 
     576          65 :                 pos = strchr(buf, ' ');
     577          65 :                 if (buf[0] == '#' || pos == NULL || pos - buf >= 20)
     578             :                         goto no_update;
     579             : 
     580          10 :                 imsi_len = pos - buf;
     581             : 
     582          15 :                 for (m = milenage_db; m; m = m->next) {
     583          25 :                         if (strncmp(buf, m->imsi, imsi_len) == 0 &&
     584          10 :                             m->imsi[imsi_len] == '\0')
     585          10 :                                 break;
     586             :                 }
     587             : 
     588          10 :                 if (!m)
     589           0 :                         goto no_update;
     590             : 
     591          10 :                 pos = buf;
     592          10 :                 pos += snprintf(pos, end - pos, "%s ", m->imsi);
     593          10 :                 pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16);
     594          10 :                 *pos++ = ' ';
     595          10 :                 pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16);
     596          10 :                 *pos++ = ' ';
     597          10 :                 pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2);
     598          10 :                 *pos++ = ' ';
     599          10 :                 pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6);
     600          10 :                 *pos++ = '\n';
     601             : 
     602             :         no_update:
     603          65 :                 fprintf(f2, "%s", buf);
     604             :         }
     605             : 
     606           5 :         fclose(f2);
     607           5 :         fclose(f);
     608             : 
     609           5 :         snprintf(name, sizeof(name), "%s.bak", fname);
     610           5 :         if (rename(fname, name) < 0) {
     611           0 :                 perror("rename");
     612           0 :                 return;
     613             :         }
     614             : 
     615           5 :         snprintf(name, sizeof(name), "%s.new", fname);
     616           5 :         if (rename(name, fname) < 0) {
     617           0 :                 perror("rename");
     618           0 :                 return;
     619             :         }
     620             : 
     621             : }
     622             : 
     623             : 
     624         101 : static struct milenage_parameters * get_milenage(const char *imsi)
     625             : {
     626         101 :         struct milenage_parameters *m = milenage_db;
     627             : 
     628         288 :         while (m) {
     629         185 :                 if (strcmp(m->imsi, imsi) == 0)
     630          99 :                         break;
     631          86 :                 m = m->next;
     632             :         }
     633             : 
     634             : #ifdef CONFIG_SQLITE
     635         101 :         if (!m)
     636           2 :                 m = db_get_milenage(imsi);
     637             : #endif /* CONFIG_SQLITE */
     638             : 
     639         101 :         return m;
     640             : }
     641             : 
     642             : 
     643          46 : static int sim_req_auth(char *imsi, char *resp, size_t resp_len)
     644             : {
     645             :         int count, max_chal, ret;
     646             :         char *pos;
     647             :         char *rpos, *rend;
     648             :         struct milenage_parameters *m;
     649             :         struct gsm_triplet *g;
     650             : 
     651          46 :         resp[0] = '\0';
     652             : 
     653          46 :         pos = strchr(imsi, ' ');
     654          46 :         if (pos) {
     655          46 :                 *pos++ = '\0';
     656          46 :                 max_chal = atoi(pos);
     657          46 :                 if (max_chal < 1 || max_chal > EAP_SIM_MAX_CHAL)
     658           0 :                         max_chal = EAP_SIM_MAX_CHAL;
     659             :         } else
     660           0 :                 max_chal = EAP_SIM_MAX_CHAL;
     661             : 
     662          46 :         rend = resp + resp_len;
     663          46 :         rpos = resp;
     664          46 :         ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
     665          46 :         if (ret < 0 || ret >= rend - rpos)
     666           0 :                 return -1;
     667          46 :         rpos += ret;
     668             : 
     669          46 :         m = get_milenage(imsi);
     670          46 :         if (m) {
     671             :                 u8 _rand[16], sres[4], kc[8];
     672         176 :                 for (count = 0; count < max_chal; count++) {
     673         132 :                         if (random_get_bytes(_rand, 16) < 0)
     674           0 :                                 return -1;
     675         132 :                         gsm_milenage(m->opc, m->ki, _rand, sres, kc);
     676         132 :                         *rpos++ = ' ';
     677         132 :                         rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
     678         132 :                         *rpos++ = ':';
     679         132 :                         rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
     680         132 :                         *rpos++ = ':';
     681         132 :                         rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
     682             :                 }
     683          44 :                 *rpos = '\0';
     684          44 :                 return 0;
     685             :         }
     686             : 
     687           2 :         count = 0;
     688           7 :         while (count < max_chal && (g = get_gsm_triplet(imsi))) {
     689           3 :                 if (strcmp(g->imsi, imsi) != 0)
     690           0 :                         continue;
     691             : 
     692           3 :                 if (rpos < rend)
     693           3 :                         *rpos++ = ' ';
     694           3 :                 rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8);
     695           3 :                 if (rpos < rend)
     696           3 :                         *rpos++ = ':';
     697           3 :                 rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4);
     698           3 :                 if (rpos < rend)
     699           3 :                         *rpos++ = ':';
     700           3 :                 rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16);
     701           3 :                 count++;
     702             :         }
     703             : 
     704           2 :         if (count == 0) {
     705           1 :                 printf("No GSM triplets found for %s\n", imsi);
     706           1 :                 ret = snprintf(rpos, rend - rpos, " FAILURE");
     707           1 :                 if (ret < 0 || ret >= rend - rpos)
     708           0 :                         return -1;
     709           1 :                 rpos += ret;
     710             :         }
     711             : 
     712           2 :         return 0;
     713             : }
     714             : 
     715             : 
     716           0 : static int gsm_auth_req(char *imsi, char *resp, size_t resp_len)
     717             : {
     718             :         int count, ret;
     719             :         char *pos, *rpos, *rend;
     720             :         struct milenage_parameters *m;
     721             : 
     722           0 :         resp[0] = '\0';
     723             : 
     724           0 :         pos = os_strchr(imsi, ' ');
     725           0 :         if (!pos)
     726           0 :                 return -1;
     727           0 :         *pos++ = '\0';
     728             : 
     729           0 :         rend = resp + resp_len;
     730           0 :         rpos = resp;
     731           0 :         ret = os_snprintf(rpos, rend - rpos, "GSM-AUTH-RESP %s", imsi);
     732           0 :         if (os_snprintf_error(rend - rpos, ret))
     733           0 :                 return -1;
     734           0 :         rpos += ret;
     735             : 
     736           0 :         m = get_milenage(imsi);
     737           0 :         if (m) {
     738             :                 u8 _rand[16], sres[4], kc[8];
     739           0 :                 for (count = 0; count < EAP_SIM_MAX_CHAL; count++) {
     740           0 :                         if (hexstr2bin(pos, _rand, 16) != 0)
     741           0 :                                 return -1;
     742           0 :                         gsm_milenage(m->opc, m->ki, _rand, sres, kc);
     743           0 :                         *rpos++ = count == 0 ? ' ' : ':';
     744           0 :                         rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
     745           0 :                         *rpos++ = ':';
     746           0 :                         rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
     747           0 :                         pos += 16 * 2;
     748           0 :                         if (*pos != ':')
     749           0 :                                 break;
     750           0 :                         pos++;
     751             :                 }
     752           0 :                 *rpos = '\0';
     753           0 :                 return 0;
     754             :         }
     755             : 
     756           0 :         printf("No GSM triplets found for %s\n", imsi);
     757           0 :         ret = os_snprintf(rpos, rend - rpos, " FAILURE");
     758           0 :         if (os_snprintf_error(rend - rpos, ret))
     759           0 :                 return -1;
     760           0 :         rpos += ret;
     761             : 
     762           0 :         return 0;
     763             : }
     764             : 
     765             : 
     766          50 : static void inc_sqn(u8 *sqn)
     767             : {
     768             :         u64 val, seq, ind;
     769             : 
     770             :         /*
     771             :          * SQN = SEQ | IND = SEQ1 | SEQ2 | IND
     772             :          *
     773             :          * The mechanism used here is not time-based, so SEQ2 is void and
     774             :          * SQN = SEQ1 | IND. The length of IND is ind_len bits and the length
     775             :          * of SEQ1 is 48 - ind_len bits.
     776             :          */
     777             : 
     778             :         /* Increment both SEQ and IND by one */
     779          50 :         val = ((u64) WPA_GET_BE32(sqn) << 16) | ((u64) WPA_GET_BE16(sqn + 4));
     780          50 :         seq = (val >> ind_len) + 1;
     781          50 :         ind = (val + 1) & ((1 << ind_len) - 1);
     782          50 :         val = (seq << ind_len) | ind;
     783          50 :         WPA_PUT_BE32(sqn, val >> 16);
     784          50 :         WPA_PUT_BE16(sqn + 4, val & 0xffff);
     785          50 : }
     786             : 
     787             : 
     788          50 : static int aka_req_auth(char *imsi, char *resp, size_t resp_len)
     789             : {
     790             :         /* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
     791             :         char *pos, *end;
     792             :         u8 _rand[EAP_AKA_RAND_LEN];
     793             :         u8 autn[EAP_AKA_AUTN_LEN];
     794             :         u8 ik[EAP_AKA_IK_LEN];
     795             :         u8 ck[EAP_AKA_CK_LEN];
     796             :         u8 res[EAP_AKA_RES_MAX_LEN];
     797             :         size_t res_len;
     798             :         int ret;
     799             :         struct milenage_parameters *m;
     800          50 :         int failed = 0;
     801             : 
     802          50 :         m = get_milenage(imsi);
     803          50 :         if (m) {
     804          50 :                 if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
     805           0 :                         return -1;
     806          50 :                 res_len = EAP_AKA_RES_MAX_LEN;
     807          50 :                 inc_sqn(m->sqn);
     808             : #ifdef CONFIG_SQLITE
     809          50 :                 db_update_milenage_sqn(m);
     810             : #endif /* CONFIG_SQLITE */
     811          50 :                 sqn_changes = 1;
     812          50 :                 if (stdout_debug) {
     813         300 :                         printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
     814         150 :                                m->sqn[0], m->sqn[1], m->sqn[2],
     815         150 :                                m->sqn[3], m->sqn[4], m->sqn[5]);
     816             :                 }
     817          50 :                 milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
     818             :                                   autn, ik, ck, res, &res_len);
     819          50 :                 if (m->res_len >= EAP_AKA_RES_MIN_LEN &&
     820           0 :                     m->res_len <= EAP_AKA_RES_MAX_LEN &&
     821           0 :                     m->res_len < res_len)
     822           0 :                         res_len = m->res_len;
     823             :         } else {
     824           0 :                 printf("Unknown IMSI: %s\n", imsi);
     825             : #ifdef AKA_USE_FIXED_TEST_VALUES
     826             :                 printf("Using fixed test values for AKA\n");
     827             :                 memset(_rand, '0', EAP_AKA_RAND_LEN);
     828             :                 memset(autn, '1', EAP_AKA_AUTN_LEN);
     829             :                 memset(ik, '3', EAP_AKA_IK_LEN);
     830             :                 memset(ck, '4', EAP_AKA_CK_LEN);
     831             :                 memset(res, '2', EAP_AKA_RES_MAX_LEN);
     832             :                 res_len = EAP_AKA_RES_MAX_LEN;
     833             : #else /* AKA_USE_FIXED_TEST_VALUES */
     834           0 :                 failed = 1;
     835             : #endif /* AKA_USE_FIXED_TEST_VALUES */
     836             :         }
     837             : 
     838          50 :         pos = resp;
     839          50 :         end = resp + resp_len;
     840          50 :         ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
     841          50 :         if (ret < 0 || ret >= end - pos)
     842           0 :                 return -1;
     843          50 :         pos += ret;
     844          50 :         if (failed) {
     845           0 :                 ret = snprintf(pos, end - pos, "FAILURE");
     846           0 :                 if (ret < 0 || ret >= end - pos)
     847           0 :                         return -1;
     848           0 :                 pos += ret;
     849           0 :                 return 0;
     850             :         }
     851          50 :         pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
     852          50 :         *pos++ = ' ';
     853          50 :         pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
     854          50 :         *pos++ = ' ';
     855          50 :         pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN);
     856          50 :         *pos++ = ' ';
     857          50 :         pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN);
     858          50 :         *pos++ = ' ';
     859          50 :         pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
     860             : 
     861          50 :         return 0;
     862             : }
     863             : 
     864             : 
     865           5 : static int aka_auts(char *imsi, char *resp, size_t resp_len)
     866             : {
     867             :         char *auts, *__rand;
     868             :         u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
     869             :         struct milenage_parameters *m;
     870             : 
     871           5 :         resp[0] = '\0';
     872             : 
     873             :         /* AKA-AUTS <IMSI> <AUTS> <RAND> */
     874             : 
     875           5 :         auts = strchr(imsi, ' ');
     876           5 :         if (auts == NULL)
     877           0 :                 return -1;
     878           5 :         *auts++ = '\0';
     879             : 
     880           5 :         __rand = strchr(auts, ' ');
     881           5 :         if (__rand == NULL)
     882           0 :                 return -1;
     883           5 :         *__rand++ = '\0';
     884             : 
     885           5 :         if (stdout_debug) {
     886           5 :                 printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n",
     887             :                        imsi, auts, __rand);
     888             :         }
     889          10 :         if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
     890           5 :             hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
     891           0 :                 printf("Could not parse AUTS/RAND\n");
     892           0 :                 return -1;
     893             :         }
     894             : 
     895           5 :         m = get_milenage(imsi);
     896           5 :         if (m == NULL) {
     897           0 :                 printf("Unknown IMSI: %s\n", imsi);
     898           0 :                 return -1;
     899             :         }
     900             : 
     901           5 :         if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
     902           1 :                 printf("AKA-AUTS: Incorrect MAC-S\n");
     903             :         } else {
     904           4 :                 memcpy(m->sqn, sqn, 6);
     905           4 :                 if (stdout_debug) {
     906          24 :                         printf("AKA-AUTS: Re-synchronized: "
     907             :                                "SQN=%02x%02x%02x%02x%02x%02x\n",
     908          24 :                                sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
     909             :                 }
     910             : #ifdef CONFIG_SQLITE
     911           4 :                 db_update_milenage_sqn(m);
     912             : #endif /* CONFIG_SQLITE */
     913           4 :                 sqn_changes = 1;
     914             :         }
     915             : 
     916           5 :         return 0;
     917             : }
     918             : 
     919             : 
     920         101 : static int process_cmd(char *cmd, char *resp, size_t resp_len)
     921             : {
     922         101 :         if (os_strncmp(cmd, "SIM-REQ-AUTH ", 13) == 0)
     923          46 :                 return sim_req_auth(cmd + 13, resp, resp_len);
     924             : 
     925          55 :         if (os_strncmp(cmd, "GSM-AUTH-REQ ", 13) == 0)
     926           0 :                 return gsm_auth_req(cmd + 13, resp, resp_len);
     927             : 
     928          55 :         if (os_strncmp(cmd, "AKA-REQ-AUTH ", 13) == 0)
     929          50 :                 return aka_req_auth(cmd + 13, resp, resp_len);
     930             : 
     931           5 :         if (os_strncmp(cmd, "AKA-AUTS ", 9) == 0)
     932           5 :                 return aka_auts(cmd + 9, resp, resp_len);
     933             : 
     934           0 :         printf("Unknown request: %s\n", cmd);
     935           0 :         return -1;
     936             : }
     937             : 
     938             : 
     939         107 : static int process(int s)
     940             : {
     941             :         char buf[1000], resp[1000];
     942             :         struct sockaddr_un from;
     943             :         socklen_t fromlen;
     944             :         ssize_t res;
     945             : 
     946         107 :         fromlen = sizeof(from);
     947         107 :         res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from,
     948             :                        &fromlen);
     949         101 :         if (res < 0) {
     950           0 :                 perror("recvfrom");
     951           0 :                 return -1;
     952             :         }
     953             : 
     954         101 :         if (res == 0)
     955           0 :                 return 0;
     956             : 
     957         101 :         if ((size_t) res >= sizeof(buf))
     958           0 :                 res = sizeof(buf) - 1;
     959         101 :         buf[res] = '\0';
     960             : 
     961         101 :         printf("Received: %s\n", buf);
     962             : 
     963         101 :         if (process_cmd(buf, resp, sizeof(resp)) < 0) {
     964           0 :                 printf("Failed to process request\n");
     965           0 :                 return -1;
     966             :         }
     967             : 
     968         101 :         if (resp[0] == '\0') {
     969           5 :                 printf("No response\n");
     970           5 :                 return 0;
     971             :         }
     972             : 
     973          96 :         printf("Send: %s\n", resp);
     974             : 
     975          96 :         if (sendto(s, resp, os_strlen(resp), 0, (struct sockaddr *) &from,
     976             :                    fromlen) < 0)
     977           0 :                 perror("send");
     978             : 
     979          96 :         return 0;
     980             : }
     981             : 
     982             : 
     983           6 : static void cleanup(void)
     984             : {
     985             :         struct gsm_triplet *g, *gprev;
     986             :         struct milenage_parameters *m, *prev;
     987             : 
     988           6 :         if (update_milenage && milenage_file && sqn_changes)
     989           5 :                 update_milenage_file(milenage_file);
     990             : 
     991           6 :         g = gsm_db;
     992          48 :         while (g) {
     993          36 :                 gprev = g;
     994          36 :                 g = g->next;
     995          36 :                 os_free(gprev);
     996             :         }
     997             : 
     998           6 :         m = milenage_db;
     999          24 :         while (m) {
    1000          12 :                 prev = m;
    1001          12 :                 m = m->next;
    1002          12 :                 os_free(prev);
    1003             :         }
    1004             : 
    1005           6 :         if (serv_sock >= 0)
    1006           6 :                 close(serv_sock);
    1007           6 :         if (socket_path)
    1008           6 :                 unlink(socket_path);
    1009             : 
    1010             : #ifdef CONFIG_SQLITE
    1011           6 :         if (sqlite_db) {
    1012           0 :                 sqlite3_close(sqlite_db);
    1013           0 :                 sqlite_db = NULL;
    1014             :         }
    1015             : #endif /* CONFIG_SQLITE */
    1016           6 : }
    1017             : 
    1018             : 
    1019           6 : static void handle_term(int sig)
    1020             : {
    1021           6 :         printf("Signal %d - terminate\n", sig);
    1022           6 :         exit(0);
    1023             : }
    1024             : 
    1025             : 
    1026          18 : static void usage(void)
    1027             : {
    1028          18 :         printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
    1029             :                "database/authenticator\n"
    1030             :                "Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>\n"
    1031             :                "\n"
    1032             :                "usage:\n"
    1033             :                "hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
    1034             :                "[-m<milenage file>] \\\n"
    1035             :                "        [-D<DB file>] [-i<IND len in bits>] [command]\n"
    1036             :                "\n"
    1037             :                "options:\n"
    1038             :                "  -h = show this usage help\n"
    1039             :                "  -u = update SQN in Milenage file on exit\n"
    1040             :                "  -s<socket path> = path for UNIX domain socket\n"
    1041             :                "                    (default: %s)\n"
    1042             :                "  -g<triplet file> = path for GSM authentication triplets\n"
    1043             :                "  -m<milenage file> = path for Milenage keys\n"
    1044             :                "  -D<DB file> = path to SQLite database\n"
    1045             :                "  -i<IND len in bits> = IND length for SQN (default: 5)\n"
    1046             :                "\n"
    1047             :                "If the optional command argument, like "
    1048             :                "\"AKA-REQ-AUTH <IMSI>\" is used, a single\n"
    1049             :                "command is processed with response sent to stdout. Otherwise, "
    1050             :                "hlr_auc_gw opens\n"
    1051             :                "a control interface and processes commands sent through it "
    1052             :                "(e.g., by EAP server\n"
    1053             :                "in hostapd).\n",
    1054             :                default_socket_path);
    1055          18 : }
    1056             : 
    1057             : 
    1058          30 : int main(int argc, char *argv[])
    1059             : {
    1060             :         int c;
    1061          30 :         char *gsm_triplet_file = NULL;
    1062          30 :         char *sqlite_db_file = NULL;
    1063          30 :         int ret = 0;
    1064             : 
    1065          30 :         if (os_program_init())
    1066           0 :                 return -1;
    1067             : 
    1068          30 :         socket_path = default_socket_path;
    1069             : 
    1070             :         for (;;) {
    1071          66 :                 c = getopt(argc, argv, "D:g:hi:m:s:u");
    1072          66 :                 if (c < 0)
    1073          12 :                         break;
    1074          54 :                 switch (c) {
    1075             :                 case 'D':
    1076             : #ifdef CONFIG_SQLITE
    1077           6 :                         sqlite_db_file = optarg;
    1078           6 :                         break;
    1079             : #else /* CONFIG_SQLITE */
    1080             :                         printf("No SQLite support included in the build\n");
    1081             :                         return -1;
    1082             : #endif /* CONFIG_SQLITE */
    1083             :                 case 'g':
    1084           6 :                         gsm_triplet_file = optarg;
    1085           6 :                         break;
    1086             :                 case 'h':
    1087           6 :                         usage();
    1088           6 :                         return 0;
    1089             :                 case 'i':
    1090          12 :                         ind_len = atoi(optarg);
    1091          12 :                         if (ind_len < 0 || ind_len > 32) {
    1092           6 :                                 printf("Invalid IND length\n");
    1093           6 :                                 return -1;
    1094             :                         }
    1095           6 :                         break;
    1096             :                 case 'm':
    1097           6 :                         milenage_file = optarg;
    1098           6 :                         break;
    1099             :                 case 's':
    1100           6 :                         socket_path = optarg;
    1101           6 :                         break;
    1102             :                 case 'u':
    1103           6 :                         update_milenage = 1;
    1104           6 :                         break;
    1105             :                 default:
    1106           6 :                         usage();
    1107           6 :                         return -1;
    1108             :                 }
    1109          36 :         }
    1110             : 
    1111          12 :         if (!gsm_triplet_file && !milenage_file && !sqlite_db_file) {
    1112           6 :                 usage();
    1113           6 :                 return -1;
    1114             :         }
    1115             : 
    1116             : #ifdef CONFIG_SQLITE
    1117           6 :         if (sqlite_db_file && (sqlite_db = db_open(sqlite_db_file)) == NULL)
    1118           0 :                 return -1;
    1119             : #endif /* CONFIG_SQLITE */
    1120             : 
    1121           6 :         if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
    1122           0 :                 return -1;
    1123             : 
    1124           6 :         if (milenage_file && read_milenage(milenage_file) < 0)
    1125           0 :                 return -1;
    1126             : 
    1127           6 :         if (optind == argc) {
    1128           6 :                 serv_sock = open_socket(socket_path);
    1129           6 :                 if (serv_sock < 0)
    1130           0 :                         return -1;
    1131             : 
    1132           6 :                 printf("Listening for requests on %s\n", socket_path);
    1133             : 
    1134           6 :                 atexit(cleanup);
    1135           6 :                 signal(SIGTERM, handle_term);
    1136           6 :                 signal(SIGINT, handle_term);
    1137             : 
    1138             :                 for (;;)
    1139         107 :                         process(serv_sock);
    1140             :         } else {
    1141             :                 char buf[1000];
    1142           0 :                 socket_path = NULL;
    1143           0 :                 stdout_debug = 0;
    1144           0 :                 if (process_cmd(argv[optind], buf, sizeof(buf)) < 0) {
    1145           0 :                         printf("FAIL\n");
    1146           0 :                         ret = -1;
    1147             :                 } else {
    1148           0 :                         printf("%s\n", buf);
    1149             :                 }
    1150           0 :                 cleanup();
    1151             :         }
    1152             : 
    1153             : #ifdef CONFIG_SQLITE
    1154           0 :         if (sqlite_db) {
    1155           0 :                 sqlite3_close(sqlite_db);
    1156           0 :                 sqlite_db = NULL;
    1157             :         }
    1158             : #endif /* CONFIG_SQLITE */
    1159             : 
    1160           0 :         os_program_deinit();
    1161             : 
    1162           0 :         return ret;
    1163             : }

Generated by: LCOV version 1.10