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
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
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
{
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
));
65 memset(data
, 0, sizeof(*data
));
66 data
->fname
= strdup(config
);
67 if (data
->fname
== NULL
) {
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
;
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
;
99 char buf
[80], *pos
, *next
;
101 f
= fopen(data
->fname
, "r");
103 wpa_printf(MSG_DEBUG
, "EAP-SIM DB: could not open triplet "
104 "file '%s'", data
->fname
);
108 if (identity_len
< 2 || identity
[0] != '1') {
109 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM DB: unexpected identity",
110 identity
, identity_len
);
116 for (i
= 0; i
< identity_len
; i
++) {
117 if (identity
[i
] == '@') {
122 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM DB: get triplets for IMSI",
123 identity
, identity_len
);
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';
130 while (*pos
!= '\0' && *pos
!= '\n')
134 if (pos
- buf
< 60 || pos
[0] == '#')
137 pos
= strchr(buf
, ':');
141 if (strlen(buf
) != identity_len
||
142 memcmp(buf
, identity
, identity_len
) != 0)
145 next
= strchr(pos
, ':');
149 if (hexstr2bin(pos
, &kc
[count
* KC_LEN
], KC_LEN
) < 0)
153 next
= strchr(pos
, ':');
157 if (hexstr2bin(pos
, &sres
[count
* SRES_LEN
], SRES_LEN
) < 0)
160 if (hexstr2bin(next
, &rand
[count
* RAND_LEN
], RAND_LEN
) < 0)
169 wpa_printf(MSG_DEBUG
, "EAP-SIM DB: no triplets found");
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
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
,
186 struct eap_sim_db_data
*data
= priv
;
191 if (identity_len
< 1 || identity
[0] != '1') {
195 f
= fopen(data
->fname
, "r");
197 wpa_printf(MSG_DEBUG
, "EAP-SIM DB: could not open triplet "
198 "file '%s'", data
->fname
);
202 if (identity_len
< 2 || identity
[0] != '1') {
203 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM DB: unexpected identity",
204 identity
, identity_len
);
209 for (i
= 0; i
< identity_len
; i
++) {
210 if (identity
[i
] == '@') {
216 while (fgets(buf
, sizeof(buf
), f
)) {
217 /* Parse IMSI:Kc:SRES:RAND and match IMSI with identity. */
218 buf
[sizeof(buf
) - 1] = '\0';
220 while (*pos
!= '\0' && *pos
!= '\n')
224 if (pos
- buf
< 60 || pos
[0] == '#')
227 pos
= strchr(buf
, ':');
231 if (strlen(buf
) != identity_len
||
232 memcmp(buf
, identity
, identity_len
) != 0)