Nuke USB_DO_ATTACH and remove device_t dv, since it is no longer needed.
[dragonfly.git] / contrib / hostapd-0.4.9 / eap_sim_db.c
bloba965fa461d264e0d930f0a4b7002be50ae4c8329
1 /*
2 * hostapd / EAP-SIM database/authenticator gateway
3 * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 /* This is an example implementation of the EAP-SIM database/authentication
16 * gateway interface that is expected to be replaced with an implementation of
17 * SS7 gateway to GSM authentication center (HLR/AuC) or a local
18 * implementation of SIM triplet generator.
20 * The example implementation here reads triplets from a text file in
21 * IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex strings. This
22 * is used to simulate an HLR/AuC. As such, it is not very useful for real life
23 * authentication, but it is useful both as an example implementation and for
24 * EAP-SIM testing.
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
31 #include "common.h"
32 #include "eap_sim_common.h"
33 #include "eap_sim_db.h"
36 /* TODO: add an alternative callback based version of the interface. This is
37 * needed to work better with the single threaded design of hostapd. For this,
38 * the EAP data has to be stored somewhere and eap_sim_db is given a context
39 * pointer for this and a callback function. The callback function will re-send
40 * the EAP data through normal operations which will eventually end up calling
41 * eap_sim_db_get_gsm_triplets() again for the same user. This time, eap_sim_db
42 * should have the triplets available immediately. */
45 struct eap_sim_db_data {
46 char *fname;
49 #define KC_LEN 8
50 #define SRES_LEN 4
51 #define RAND_LEN 16
54 /* Initialize EAP-SIM database/authentication gateway interface.
55 * Returns pointer to a private data structure. */
56 void * eap_sim_db_init(const char *config)
58 struct eap_sim_db_data *data;
60 data = malloc(sizeof(*data));
61 if (data == NULL) {
62 return NULL;
65 memset(data, 0, sizeof(*data));
66 data->fname = strdup(config);
67 if (data->fname == NULL) {
68 free(data);
69 return NULL;
72 return data;
75 /* Deinitialize EAP-SIM database/authentication gateway interface.
76 * priv is the pointer from eap_sim_db_init(). */
77 void eap_sim_db_deinit(void *priv)
79 struct eap_sim_db_data *data = priv;
80 free(data->fname);
81 free(data);
85 /* Get GSM triplets for user name identity (identity_len bytes). In most cases,
86 * the user name is '1' | IMSI, i.e., 1 followed by the IMSI in ASCII format.
87 * The identity may also include NAI realm (@realm).
88 * priv is the pointer from eap_sim_db_init().
89 * Returns the number of triplets received (has to be less than or equal to
90 * max_chal) or -1 on error (e.g., user not found). rand, kc, and sres are
91 * pointers to data areas for the triplets. */
92 int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity,
93 size_t identity_len, int max_chal,
94 u8 *rand, u8 *kc, u8 *sres)
96 struct eap_sim_db_data *data = priv;
97 FILE *f;
98 int count, i;
99 char buf[80], *pos, *next;
101 f = fopen(data->fname, "r");
102 if (f == NULL) {
103 wpa_printf(MSG_DEBUG, "EAP-SIM DB: could not open triplet "
104 "file '%s'", data->fname);
105 return -1;
108 if (identity_len < 2 || identity[0] != '1') {
109 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
110 identity, identity_len);
111 fclose(f);
112 return -1;
114 identity++;
115 identity_len--;
116 for (i = 0; i < identity_len; i++) {
117 if (identity[i] == '@') {
118 identity_len = i;
119 break;
122 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: get triplets for IMSI",
123 identity, identity_len);
125 count = 0;
126 while (count < max_chal && fgets(buf, sizeof(buf), f)) {
127 /* Parse IMSI:Kc:SRES:RAND and match IMSI with identity. */
128 buf[sizeof(buf) - 1] = '\0';
129 pos = buf;
130 while (*pos != '\0' && *pos != '\n')
131 pos++;
132 if (*pos == '\n')
133 *pos = '\0';
134 if (pos - buf < 60 || pos[0] == '#')
135 continue;
137 pos = strchr(buf, ':');
138 if (pos == NULL)
139 continue;
140 *pos++ = '\0';
141 if (strlen(buf) != identity_len ||
142 memcmp(buf, identity, identity_len) != 0)
143 continue;
145 next = strchr(pos, ':');
146 if (next == NULL)
147 continue;
148 *next++ = '\0';
149 if (hexstr2bin(pos, &kc[count * KC_LEN], KC_LEN) < 0)
150 continue;
152 pos = next;
153 next = strchr(pos, ':');
154 if (next == NULL)
155 continue;
156 *next++ = '\0';
157 if (hexstr2bin(pos, &sres[count * SRES_LEN], SRES_LEN) < 0)
158 continue;
160 if (hexstr2bin(next, &rand[count * RAND_LEN], RAND_LEN) < 0)
161 continue;
163 count++;
166 fclose(f);
168 if (count == 0) {
169 wpa_printf(MSG_DEBUG, "EAP-SIM DB: no triplets found");
170 count = -1;
173 return count;
177 /* Verify whether the given user identity (identity_len bytes) is known. In
178 * most cases, the user name is '1' | IMSI, i.e., 1 followed by the IMSI in
179 * ASCII format.
180 * priv is the pointer from eap_sim_db_init().
181 * Returns 0 if the user is found and GSM triplets would be available for it or
182 * -1 on error (e.g., user not found or no triplets available). */
183 int eap_sim_db_identity_known(void *priv, const u8 *identity,
184 size_t identity_len)
186 struct eap_sim_db_data *data = priv;
187 FILE *f;
188 char buf[80], *pos;
189 int i;
191 if (identity_len < 1 || identity[0] != '1') {
192 return -1;
195 f = fopen(data->fname, "r");
196 if (f == NULL) {
197 wpa_printf(MSG_DEBUG, "EAP-SIM DB: could not open triplet "
198 "file '%s'", data->fname);
199 return -1;
202 if (identity_len < 2 || identity[0] != '1') {
203 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
204 identity, identity_len);
205 return -1;
207 identity++;
208 identity_len--;
209 for (i = 0; i < identity_len; i++) {
210 if (identity[i] == '@') {
211 identity_len = i;
212 break;
216 while (fgets(buf, sizeof(buf), f)) {
217 /* Parse IMSI:Kc:SRES:RAND and match IMSI with identity. */
218 buf[sizeof(buf) - 1] = '\0';
219 pos = buf;
220 while (*pos != '\0' && *pos != '\n')
221 pos++;
222 if (*pos == '\n')
223 *pos = '\0';
224 if (pos - buf < 60 || pos[0] == '#')
225 continue;
227 pos = strchr(buf, ':');
228 if (pos == NULL)
229 continue;
230 *pos++ = '\0';
231 if (strlen(buf) != identity_len ||
232 memcmp(buf, identity, identity_len) != 0)
233 continue;
235 fclose(f);
236 return 0;
239 /* IMSI not found */
241 fclose(f);
242 return -1;