1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This is an example implementation of the EAP-SIM/AKA database/authentication
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * gateway interface to HLR/AuC. It is expected to be replaced with an
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * a local implementation of SIM triplet and AKA authentication data generator.
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * hostapd will send SIM/AKA authentication queries over a UNIX domain socket
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * to and external program, e.g., this hlr_auc_gw. This interface uses simple
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * text-based format:
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP-SIM / GSM triplet query/response:
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * SIM-REQ-AUTH <IMSI> <max_chal>
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3]
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * SIM-RESP-AUTH <IMSI> FAILURE
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP-AKA / UMTS query/response:
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * AKA-REQ-AUTH <IMSI>
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * AKA-RESP-AUTH <IMSI> FAILURE
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP-AKA / UMTS AUTS (re-synchronization):
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * AKA-AUTS <IMSI> <AUTS> <RAND>
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IMSI and max_chal are sent as an ASCII string,
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * The example implementation here reads GSM authentication triplets from a
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * strings. This is used to simulate an HLR/AuC. As such, it is not very useful
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * for real life authentication, but it is useful both as an example
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * implementation and for EAP-SIM testing.
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/un.h>
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "milenage.h"
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const char *socket_path;
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int serv_sock = -1;
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* GSM triplets */
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct gsm_triplet {
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct gsm_triplet *next;
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char imsi[20];
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 kc[8];
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 sres[4];
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 _rand[16];
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL;
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct milenage_parameters {
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct milenage_parameters *next;
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char imsi[20];
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 ki[16];
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 opc[16];
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 amf[2];
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 sqn[6];
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct milenage_parameters *milenage_db = NULL;
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_SIM_MAX_CHAL 3
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_AKA_RAND_LEN 16
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_AKA_AUTN_LEN 16
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_AKA_AUTS_LEN 14
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_AKA_RES_MAX_LEN 16
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_AKA_IK_LEN 16
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_AKA_CK_LEN 16
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int open_socket(const char *path)
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct sockaddr_un addr;
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int s;
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	s = socket(PF_UNIX, SOCK_DGRAM, 0);
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (s < 0) {
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("socket(PF_UNIX)");
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	memset(&addr, 0, sizeof(addr));
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	addr.sun_family = AF_UNIX;
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("bind(PF_UNIX)");
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		close(s);
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return s;
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int read_gsm_triplets(const char *fname)
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	FILE *f;
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[200], *pos, *pos2;
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct gsm_triplet *g = NULL;
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int line, ret = 0;
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (fname == NULL)
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	f = fopen(fname, "r");
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (f == NULL) {
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("Could not open GSM tripler data file '%s'\n", fname);
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	line = 0;
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (fgets(buf, sizeof(buf), f)) {
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		line++;
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Parse IMSI:Kc:SRES:RAND */
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		buf[sizeof(buf) - 1] = '\0';
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (buf[0] == '#')
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = buf;
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		while (*pos != '\0' && *pos != '\n')
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos++;
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos == '\n')
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*pos = '\0';
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = buf;
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos == '\0')
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		g = os_zalloc(sizeof(*g));
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (g == NULL) {
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* IMSI */
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ':');
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid IMSI (%s)\n",
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       fname, line, pos);
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2 = '\0';
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) >= sizeof(g->imsi)) {
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Too long IMSI (%s)\n",
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       fname, line, pos);
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_strlcpy(g->imsi, pos, sizeof(g->imsi));
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Kc */
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ':');
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2 = '\0';
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* SRES */
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ':');
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid SRES (%s)\n", fname, line,
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       pos);
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2 = '\0';
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) {
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid SRES (%s)\n", fname, line,
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       pos);
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* RAND */
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ':');
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2)
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*pos2 = '\0';
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) {
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid RAND (%s)\n", fname, line,
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       pos);
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		g->next = gsm_db;
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		gsm_db = g;
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		g = NULL;
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	free(g);
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fclose(f);
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct gsm_triplet * get_gsm_triplet(const char *imsi)
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct gsm_triplet *g = gsm_db_pos;
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (g) {
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strcmp(g->imsi, imsi) == 0) {
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			gsm_db_pos = g->next;
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return g;
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		g = g->next;
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	g = gsm_db;
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (g && g != gsm_db_pos) {
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strcmp(g->imsi, imsi) == 0) {
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			gsm_db_pos = g->next;
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return g;
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		g = g->next;
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return NULL;
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int read_milenage(const char *fname)
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	FILE *f;
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[200], *pos, *pos2;
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct milenage_parameters *m = NULL;
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int line, ret = 0;
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (fname == NULL)
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	f = fopen(fname, "r");
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (f == NULL) {
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("Could not open Milenage data file '%s'\n", fname);
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	line = 0;
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (fgets(buf, sizeof(buf), f)) {
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		line++;
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Parse IMSI Ki OPc AMF SQN */
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		buf[sizeof(buf) - 1] = '\0';
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (buf[0] == '#')
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = buf;
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		while (*pos != '\0' && *pos != '\n')
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos++;
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos == '\n')
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*pos = '\0';
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = buf;
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos == '\0')
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		m = os_zalloc(sizeof(*m));
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (m == NULL) {
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* IMSI */
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ' ');
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid IMSI (%s)\n",
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       fname, line, pos);
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2 = '\0';
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) >= sizeof(m->imsi)) {
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Too long IMSI (%s)\n",
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       fname, line, pos);
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_strlcpy(m->imsi, pos, sizeof(m->imsi));
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Ki */
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ' ');
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2 = '\0';
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) {
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* OPc */
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ' ');
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2 = '\0';
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) {
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* AMF */
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ' ');
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2 = '\0';
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* SQN */
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = strchr(pos, ' ');
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2)
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*pos2 = '\0';
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) {
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = pos2 + 1;
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		m->next = milenage_db;
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		milenage_db = m;
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		m = NULL;
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	free(m);
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fclose(f);
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct milenage_parameters * get_milenage(const char *imsi)
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct milenage_parameters *m = milenage_db;
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (m) {
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strcmp(m->imsi, imsi) == 0)
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		m = m->next;
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return m;
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 char *imsi)
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int count, max_chal, ret;
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *pos;
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char reply[1000], *rpos, *rend;
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct milenage_parameters *m;
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct gsm_triplet *g;
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	reply[0] = '\0';
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = strchr(imsi, ' ');
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos) {
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos++ = '\0';
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		max_chal = atoi(pos);
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL)
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			max_chal = EAP_SIM_MAX_CHAL;
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		max_chal = EAP_SIM_MAX_CHAL;
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	rend = &reply[sizeof(reply)];
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	rpos = reply;
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret < 0 || ret >= rend - rpos)
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	rpos += ret;
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	m = get_milenage(imsi);
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (m) {
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		u8 _rand[16], sres[4], kc[8];
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (count = 0; count < max_chal; count++) {
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (os_get_random(_rand, 16) < 0)
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				return;
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			gsm_milenage(m->opc, m->ki, _rand, sres, kc);
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*rpos++ = ' ';
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*rpos++ = ':';
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*rpos++ = ':';
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*rpos = '\0';
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto send;
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	count = 0;
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (count < max_chal && (g = get_gsm_triplet(imsi))) {
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (strcmp(g->imsi, imsi) != 0)
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (rpos < rend)
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*rpos++ = ' ';
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8);
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (rpos < rend)
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*rpos++ = ':';
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4);
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (rpos < rend)
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*rpos++ = ':';
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16);
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		count++;
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (count == 0) {
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("No GSM triplets found for %s\n", imsi);
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = snprintf(rpos, rend - rpos, " FAILURE");
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret < 0 || ret >= rend - rpos)
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return;
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		rpos += ret;
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtsend:
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	printf("Send: %s\n", reply);
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sendto(s, reply, rpos - reply, 0,
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (struct sockaddr *) from, fromlen) < 0)
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("send");
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 char *imsi)
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char reply[1000], *pos, *end;
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 _rand[EAP_AKA_RAND_LEN];
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 autn[EAP_AKA_AUTN_LEN];
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 ik[EAP_AKA_IK_LEN];
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 ck[EAP_AKA_CK_LEN];
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 res[EAP_AKA_RES_MAX_LEN];
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t res_len;
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret;
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct milenage_parameters *m;
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	m = get_milenage(imsi);
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (m) {
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (os_get_random(_rand, EAP_AKA_RAND_LEN) < 0)
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return;
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		res_len = EAP_AKA_RES_MAX_LEN;
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		inc_byte_array(m->sqn, 6);
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       m->sqn[0], m->sqn[1], m->sqn[2],
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       m->sqn[3], m->sqn[4], m->sqn[5]);
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  autn, ik, ck, res, &res_len);
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("Unknown IMSI: %s\n", imsi);
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef AKA_USE_FIXED_TEST_VALUES
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("Using fixed test values for AKA\n");
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		memset(_rand, '0', EAP_AKA_RAND_LEN);
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		memset(autn, '1', EAP_AKA_AUTN_LEN);
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		memset(ik, '3', EAP_AKA_IK_LEN);
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		memset(ck, '4', EAP_AKA_CK_LEN);
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		memset(res, '2', EAP_AKA_RES_MAX_LEN);
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		res_len = EAP_AKA_RES_MAX_LEN;
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* AKA_USE_FIXED_TEST_VALUES */
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* AKA_USE_FIXED_TEST_VALUES */
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = reply;
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	end = &reply[sizeof(reply)];
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret < 0 || ret >= end - pos)
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += ret;
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*pos++ = ' ';
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*pos++ = ' ';
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN);
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*pos++ = ' ';
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN);
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*pos++ = ' ';
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	printf("Send: %s\n", reply);
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   fromlen) < 0)
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("send");
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		     char *imsi)
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
535dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt	char *auts, *__rand;
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct milenage_parameters *m;
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* AKA-AUTS <IMSI> <AUTS> <RAND> */
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	auts = strchr(imsi, ' ');
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (auts == NULL)
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*auts++ = '\0';
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
546dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt	__rand = strchr(auts, ' ');
547dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt	if (__rand == NULL)
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
549dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt	*__rand++ = '\0';
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
551dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt	printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand);
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
553dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt	    hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("Could not parse AUTS/RAND\n");
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	m = get_milenage(imsi);
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (m == NULL) {
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("Unknown IMSI: %s\n", imsi);
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("AKA-AUTS: Incorrect MAC-S\n");
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		memcpy(m->sqn, sqn, 6);
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("AKA-AUTS: Re-synchronized: "
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       "SQN=%02x%02x%02x%02x%02x%02x\n",
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int process(int s)
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[1000];
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct sockaddr_un from;
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	socklen_t fromlen;
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ssize_t res;
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fromlen = sizeof(from);
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from,
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       &fromlen);
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0) {
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		perror("recvfrom");
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res == 0)
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((size_t) res >= sizeof(buf))
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		res = sizeof(buf) - 1;
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buf[res] = '\0';
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	printf("Received: %s\n", buf);
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sim_req_auth(s, &from, fromlen, buf + 13);
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		aka_req_auth(s, &from, fromlen, buf + 13);
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		aka_auts(s, &from, fromlen, buf + 9);
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		printf("Unknown request: %s\n", buf);
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void cleanup(void)
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct gsm_triplet *g, *gprev;
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct milenage_parameters *m, *prev;
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	g = gsm_db;
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (g) {
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		gprev = g;
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		g = g->next;
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		free(gprev);
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	m = milenage_db;
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (m) {
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		prev = m;
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		m = m->next;
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		free(prev);
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	close(serv_sock);
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	unlink(socket_path);
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void handle_term(int sig)
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	printf("Signal %d - terminate\n", sig);
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	exit(0);
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void usage(void)
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "database/authenticator\n"
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>\n"
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "\n"
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "usage:\n"
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] "
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "[-m<milenage file>]\n"
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "\n"
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "options:\n"
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "  -h = show this usage help\n"
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "  -s<socket path> = path for UNIX domain socket\n"
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "                    (default: %s)\n"
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "  -g<triplet file> = path for GSM authentication triplets\n"
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       "  -m<milenage file> = path for Milenage keys\n",
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       default_socket_path);
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint main(int argc, char *argv[])
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int c;
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *milenage_file = NULL;
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *gsm_triplet_file = NULL;
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	socket_path = default_socket_path;
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (;;) {
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		c = getopt(argc, argv, "g:hm:s:");
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (c < 0)
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		switch (c) {
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		case 'g':
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			gsm_triplet_file = optarg;
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		case 'h':
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			usage();
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return 0;
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		case 'm':
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			milenage_file = optarg;
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		case 's':
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			socket_path = optarg;
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		default:
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			usage();
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (milenage_file && read_milenage(milenage_file) < 0)
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	serv_sock = open_socket(socket_path);
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (serv_sock < 0)
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	printf("Listening for requests on %s\n", socket_path);
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	atexit(cleanup);
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	signal(SIGTERM, handle_term);
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	signal(SIGINT, handle_term);
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (;;)
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		process(serv_sock);
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
715