Updated to hostap_2_6
[mech_eap.git] / libeap / src / eap_server / eap_sim_db.c
1 /*
2  * hostapd / EAP-SIM database/authenticator gateway
3  * Copyright (c) 2005-2010, 2012, 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 that is using an external program as an SS7 gateway to
10  * GSM/UMTS authentication center (HLR/AuC). hlr_auc_gw is an example
11  * implementation of such a gateway program. This eap_sim_db.c takes care of
12  * EAP-SIM/AKA pseudonyms and re-auth identities. It can be used with different
13  * gateway implementations for HLR/AuC access. Alternatively, it can also be
14  * completely replaced if the in-memory database of pseudonyms/re-auth
15  * identities is not suitable for some cases.
16  */
17
18 #include "includes.h"
19 #include <sys/un.h>
20 #ifdef CONFIG_SQLITE
21 #include <sqlite3.h>
22 #endif /* CONFIG_SQLITE */
23
24 #include "common.h"
25 #include "crypto/random.h"
26 #include "eap_common/eap_sim_common.h"
27 #include "eap_server/eap_sim_db.h"
28 #include "eloop.h"
29
30 struct eap_sim_pseudonym {
31         struct eap_sim_pseudonym *next;
32         char *permanent; /* permanent username */
33         char *pseudonym; /* pseudonym username */
34 };
35
36 struct eap_sim_db_pending {
37         struct eap_sim_db_pending *next;
38         char imsi[20];
39         enum { PENDING, SUCCESS, FAILURE } state;
40         void *cb_session_ctx;
41         int aka;
42         union {
43                 struct {
44                         u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN];
45                         u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN];
46                         u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN];
47                         int num_chal;
48                 } sim;
49                 struct {
50                         u8 rand[EAP_AKA_RAND_LEN];
51                         u8 autn[EAP_AKA_AUTN_LEN];
52                         u8 ik[EAP_AKA_IK_LEN];
53                         u8 ck[EAP_AKA_CK_LEN];
54                         u8 res[EAP_AKA_RES_MAX_LEN];
55                         size_t res_len;
56                 } aka;
57         } u;
58 };
59
60 struct eap_sim_db_data {
61         int sock;
62         char *fname;
63         char *local_sock;
64         void (*get_complete_cb)(void *ctx, void *session_ctx);
65         void *ctx;
66         struct eap_sim_pseudonym *pseudonyms;
67         struct eap_sim_reauth *reauths;
68         struct eap_sim_db_pending *pending;
69         unsigned int eap_sim_db_timeout;
70 #ifdef CONFIG_SQLITE
71         sqlite3 *sqlite_db;
72         char db_tmp_identity[100];
73         char db_tmp_pseudonym_str[100];
74         struct eap_sim_pseudonym db_tmp_pseudonym;
75         struct eap_sim_reauth db_tmp_reauth;
76 #endif /* CONFIG_SQLITE */
77 };
78
79
80 static void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx);
81 static void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx);
82
83
84 #ifdef CONFIG_SQLITE
85
86 static int db_table_exists(sqlite3 *db, const char *name)
87 {
88         char cmd[128];
89         os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
90         return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
91 }
92
93
94 static int db_table_create_pseudonym(sqlite3 *db)
95 {
96         char *err = NULL;
97         const char *sql =
98                 "CREATE TABLE pseudonyms("
99                 "  permanent CHAR(21) PRIMARY KEY,"
100                 "  pseudonym CHAR(21) NOT NULL"
101                 ");";
102
103         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
104                    "pseudonym information");
105         if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
106                 wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
107                 sqlite3_free(err);
108                 return -1;
109         }
110
111         return 0;
112 }
113
114
115 static int db_table_create_reauth(sqlite3 *db)
116 {
117         char *err = NULL;
118         const char *sql =
119                 "CREATE TABLE reauth("
120                 "  permanent CHAR(21) PRIMARY KEY,"
121                 "  reauth_id CHAR(21) NOT NULL,"
122                 "  counter INTEGER,"
123                 "  mk CHAR(40),"
124                 "  k_encr CHAR(32),"
125                 "  k_aut CHAR(64),"
126                 "  k_re CHAR(64)"
127                 ");";
128
129         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
130                    "reauth information");
131         if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
132                 wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
133                 sqlite3_free(err);
134                 return -1;
135         }
136
137         return 0;
138 }
139
140
141 static sqlite3 * db_open(const char *db_file)
142 {
143         sqlite3 *db;
144
145         if (sqlite3_open(db_file, &db)) {
146                 wpa_printf(MSG_ERROR, "EAP-SIM DB: Failed to open database "
147                            "%s: %s", db_file, sqlite3_errmsg(db));
148                 sqlite3_close(db);
149                 return NULL;
150         }
151
152         if (!db_table_exists(db, "pseudonyms") &&
153             db_table_create_pseudonym(db) < 0) {
154                 sqlite3_close(db);
155                 return NULL;
156         }
157
158         if (!db_table_exists(db, "reauth") &&
159             db_table_create_reauth(db) < 0) {
160                 sqlite3_close(db);
161                 return NULL;
162         }
163
164         return db;
165 }
166
167
168 static int valid_db_string(const char *str)
169 {
170         const char *pos = str;
171         while (*pos) {
172                 if ((*pos < '0' || *pos > '9') &&
173                     (*pos < 'a' || *pos > 'f'))
174                         return 0;
175                 pos++;
176         }
177         return 1;
178 }
179
180
181 static int db_add_pseudonym(struct eap_sim_db_data *data,
182                             const char *permanent, char *pseudonym)
183 {
184         char cmd[128];
185         char *err = NULL;
186
187         if (!valid_db_string(permanent) || !valid_db_string(pseudonym)) {
188                 os_free(pseudonym);
189                 return -1;
190         }
191
192         os_snprintf(cmd, sizeof(cmd), "INSERT OR REPLACE INTO pseudonyms "
193                     "(permanent, pseudonym) VALUES ('%s', '%s');",
194                     permanent, pseudonym);
195         os_free(pseudonym);
196         if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
197         {
198                 wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
199                 sqlite3_free(err);
200                 return -1;
201         }
202
203         return 0;
204 }
205
206
207 static int get_pseudonym_cb(void *ctx, int argc, char *argv[], char *col[])
208 {
209         struct eap_sim_db_data *data = ctx;
210         int i;
211
212         for (i = 0; i < argc; i++) {
213                 if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
214                         os_strlcpy(data->db_tmp_identity, argv[i],
215                                    sizeof(data->db_tmp_identity));
216                 }
217         }
218
219         return 0;
220 }
221
222
223 static char *
224 db_get_pseudonym(struct eap_sim_db_data *data, const char *pseudonym)
225 {
226         char cmd[128];
227
228         if (!valid_db_string(pseudonym))
229                 return NULL;
230         os_memset(&data->db_tmp_identity, 0, sizeof(data->db_tmp_identity));
231         os_snprintf(cmd, sizeof(cmd),
232                     "SELECT permanent FROM pseudonyms WHERE pseudonym='%s';",
233                     pseudonym);
234         if (sqlite3_exec(data->sqlite_db, cmd, get_pseudonym_cb, data, NULL) !=
235             SQLITE_OK)
236                 return NULL;
237         if (data->db_tmp_identity[0] == '\0')
238                 return NULL;
239         return data->db_tmp_identity;
240 }
241
242
243 static int db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
244                          char *reauth_id, u16 counter, const u8 *mk,
245                          const u8 *k_encr, const u8 *k_aut, const u8 *k_re)
246 {
247         char cmd[2000], *pos, *end;
248         char *err = NULL;
249
250         if (!valid_db_string(permanent) || !valid_db_string(reauth_id)) {
251                 os_free(reauth_id);
252                 return -1;
253         }
254
255         pos = cmd;
256         end = pos + sizeof(cmd);
257         pos += os_snprintf(pos, end - pos, "INSERT OR REPLACE INTO reauth "
258                            "(permanent, reauth_id, counter%s%s%s%s) "
259                            "VALUES ('%s', '%s', %u",
260                            mk ? ", mk" : "",
261                            k_encr ? ", k_encr" : "",
262                            k_aut ? ", k_aut" : "",
263                            k_re ? ", k_re" : "",
264                            permanent, reauth_id, counter);
265         os_free(reauth_id);
266
267         if (mk) {
268                 pos += os_snprintf(pos, end - pos, ", '");
269                 pos += wpa_snprintf_hex(pos, end - pos, mk, EAP_SIM_MK_LEN);
270                 pos += os_snprintf(pos, end - pos, "'");
271         }
272
273         if (k_encr) {
274                 pos += os_snprintf(pos, end - pos, ", '");
275                 pos += wpa_snprintf_hex(pos, end - pos, k_encr,
276                                         EAP_SIM_K_ENCR_LEN);
277                 pos += os_snprintf(pos, end - pos, "'");
278         }
279
280         if (k_aut) {
281                 pos += os_snprintf(pos, end - pos, ", '");
282                 pos += wpa_snprintf_hex(pos, end - pos, k_aut,
283                                         EAP_AKA_PRIME_K_AUT_LEN);
284                 pos += os_snprintf(pos, end - pos, "'");
285         }
286
287         if (k_re) {
288                 pos += os_snprintf(pos, end - pos, ", '");
289                 pos += wpa_snprintf_hex(pos, end - pos, k_re,
290                                         EAP_AKA_PRIME_K_RE_LEN);
291                 pos += os_snprintf(pos, end - pos, "'");
292         }
293
294         os_snprintf(pos, end - pos, ");");
295
296         if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
297         {
298                 wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
299                 sqlite3_free(err);
300                 return -1;
301         }
302
303         return 0;
304 }
305
306
307 static int get_reauth_cb(void *ctx, int argc, char *argv[], char *col[])
308 {
309         struct eap_sim_db_data *data = ctx;
310         int i;
311         struct eap_sim_reauth *reauth = &data->db_tmp_reauth;
312
313         for (i = 0; i < argc; i++) {
314                 if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
315                         os_strlcpy(data->db_tmp_identity, argv[i],
316                                    sizeof(data->db_tmp_identity));
317                         reauth->permanent = data->db_tmp_identity;
318                 } else if (os_strcmp(col[i], "counter") == 0 && argv[i]) {
319                         reauth->counter = atoi(argv[i]);
320                 } else if (os_strcmp(col[i], "mk") == 0 && argv[i]) {
321                         hexstr2bin(argv[i], reauth->mk, sizeof(reauth->mk));
322                 } else if (os_strcmp(col[i], "k_encr") == 0 && argv[i]) {
323                         hexstr2bin(argv[i], reauth->k_encr,
324                                    sizeof(reauth->k_encr));
325                 } else if (os_strcmp(col[i], "k_aut") == 0 && argv[i]) {
326                         hexstr2bin(argv[i], reauth->k_aut,
327                                    sizeof(reauth->k_aut));
328                 } else if (os_strcmp(col[i], "k_re") == 0 && argv[i]) {
329                         hexstr2bin(argv[i], reauth->k_re,
330                                    sizeof(reauth->k_re));
331                 }
332         }
333
334         return 0;
335 }
336
337
338 static struct eap_sim_reauth *
339 db_get_reauth(struct eap_sim_db_data *data, const char *reauth_id)
340 {
341         char cmd[256];
342
343         if (!valid_db_string(reauth_id))
344                 return NULL;
345         os_memset(&data->db_tmp_reauth, 0, sizeof(data->db_tmp_reauth));
346         os_strlcpy(data->db_tmp_pseudonym_str, reauth_id,
347                    sizeof(data->db_tmp_pseudonym_str));
348         data->db_tmp_reauth.reauth_id = data->db_tmp_pseudonym_str;
349         os_snprintf(cmd, sizeof(cmd),
350                     "SELECT * FROM reauth WHERE reauth_id='%s';", reauth_id);
351         if (sqlite3_exec(data->sqlite_db, cmd, get_reauth_cb, data, NULL) !=
352             SQLITE_OK)
353                 return NULL;
354         if (data->db_tmp_reauth.permanent == NULL)
355                 return NULL;
356         return &data->db_tmp_reauth;
357 }
358
359
360 static void db_remove_reauth(struct eap_sim_db_data *data,
361                              struct eap_sim_reauth *reauth)
362 {
363         char cmd[256];
364
365         if (!valid_db_string(reauth->permanent))
366                 return;
367         os_snprintf(cmd, sizeof(cmd),
368                     "DELETE FROM reauth WHERE permanent='%s';",
369                     reauth->permanent);
370         sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, NULL);
371 }
372
373 #endif /* CONFIG_SQLITE */
374
375
376 static struct eap_sim_db_pending *
377 eap_sim_db_get_pending(struct eap_sim_db_data *data, const char *imsi, int aka)
378 {
379         struct eap_sim_db_pending *entry, *prev = NULL;
380
381         entry = data->pending;
382         while (entry) {
383                 if (entry->aka == aka && os_strcmp(entry->imsi, imsi) == 0) {
384                         if (prev)
385                                 prev->next = entry->next;
386                         else
387                                 data->pending = entry->next;
388                         break;
389                 }
390                 prev = entry;
391                 entry = entry->next;
392         }
393         return entry;
394 }
395
396
397 static void eap_sim_db_add_pending(struct eap_sim_db_data *data,
398                                    struct eap_sim_db_pending *entry)
399 {
400         entry->next = data->pending;
401         data->pending = entry;
402 }
403
404
405 static void eap_sim_db_free_pending(struct eap_sim_db_data *data,
406                                     struct eap_sim_db_pending *entry)
407 {
408         eloop_cancel_timeout(eap_sim_db_query_timeout, data, entry);
409         eloop_cancel_timeout(eap_sim_db_del_timeout, data, entry);
410         os_free(entry);
411 }
412
413
414 static void eap_sim_db_del_pending(struct eap_sim_db_data *data,
415                                    struct eap_sim_db_pending *entry)
416 {
417         struct eap_sim_db_pending **pp = &data->pending;
418
419         while (*pp != NULL) {
420                 if (*pp == entry) {
421                         *pp = entry->next;
422                         eap_sim_db_free_pending(data, entry);
423                         return;
424                 }
425                 pp = &(*pp)->next;
426         }
427 }
428
429
430 static void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx)
431 {
432         struct eap_sim_db_data *data = eloop_ctx;
433         struct eap_sim_db_pending *entry = user_ctx;
434
435         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Delete query timeout for %p", entry);
436         eap_sim_db_del_pending(data, entry);
437 }
438
439
440 static void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx)
441 {
442         struct eap_sim_db_data *data = eloop_ctx;
443         struct eap_sim_db_pending *entry = user_ctx;
444
445         /*
446          * Report failure and allow some time for EAP server to process it
447          * before deleting the query.
448          */
449         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Query timeout for %p", entry);
450         entry->state = FAILURE;
451         data->get_complete_cb(data->ctx, entry->cb_session_ctx);
452         eloop_register_timeout(1, 0, eap_sim_db_del_timeout, data, entry);
453 }
454
455
456 static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
457                                      const char *imsi, char *buf)
458 {
459         char *start, *end, *pos;
460         struct eap_sim_db_pending *entry;
461         int num_chal;
462
463         /*
464          * SIM-RESP-AUTH <IMSI> Kc(i):SRES(i):RAND(i) ...
465          * SIM-RESP-AUTH <IMSI> FAILURE
466          * (IMSI = ASCII string, Kc/SRES/RAND = hex string)
467          */
468
469         entry = eap_sim_db_get_pending(data, imsi, 0);
470         if (entry == NULL) {
471                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
472                            "received message found");
473                 return;
474         }
475
476         start = buf;
477         if (os_strncmp(start, "FAILURE", 7) == 0) {
478                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
479                            "failure");
480                 entry->state = FAILURE;
481                 eap_sim_db_add_pending(data, entry);
482                 data->get_complete_cb(data->ctx, entry->cb_session_ctx);
483                 return;
484         }
485
486         num_chal = 0;
487         while (num_chal < EAP_SIM_MAX_CHAL) {
488                 end = os_strchr(start, ' ');
489                 if (end)
490                         *end = '\0';
491
492                 pos = os_strchr(start, ':');
493                 if (pos == NULL)
494                         goto parse_fail;
495                 *pos = '\0';
496                 if (hexstr2bin(start, entry->u.sim.kc[num_chal],
497                                EAP_SIM_KC_LEN))
498                         goto parse_fail;
499
500                 start = pos + 1;
501                 pos = os_strchr(start, ':');
502                 if (pos == NULL)
503                         goto parse_fail;
504                 *pos = '\0';
505                 if (hexstr2bin(start, entry->u.sim.sres[num_chal],
506                                EAP_SIM_SRES_LEN))
507                         goto parse_fail;
508
509                 start = pos + 1;
510                 if (hexstr2bin(start, entry->u.sim.rand[num_chal],
511                                GSM_RAND_LEN))
512                         goto parse_fail;
513
514                 num_chal++;
515                 if (end == NULL)
516                         break;
517                 else
518                         start = end + 1;
519         }
520         entry->u.sim.num_chal = num_chal;
521
522         entry->state = SUCCESS;
523         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
524                    "successfully - callback");
525         eap_sim_db_add_pending(data, entry);
526         data->get_complete_cb(data->ctx, entry->cb_session_ctx);
527         return;
528
529 parse_fail:
530         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
531         eap_sim_db_free_pending(data, entry);
532 }
533
534
535 static void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data,
536                                      const char *imsi, char *buf)
537 {
538         char *start, *end;
539         struct eap_sim_db_pending *entry;
540
541         /*
542          * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
543          * AKA-RESP-AUTH <IMSI> FAILURE
544          * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string)
545          */
546
547         entry = eap_sim_db_get_pending(data, imsi, 1);
548         if (entry == NULL) {
549                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
550                            "received message found");
551                 return;
552         }
553
554         start = buf;
555         if (os_strncmp(start, "FAILURE", 7) == 0) {
556                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
557                            "failure");
558                 entry->state = FAILURE;
559                 eap_sim_db_add_pending(data, entry);
560                 data->get_complete_cb(data->ctx, entry->cb_session_ctx);
561                 return;
562         }
563
564         end = os_strchr(start, ' ');
565         if (end == NULL)
566                 goto parse_fail;
567         *end = '\0';
568         if (hexstr2bin(start, entry->u.aka.rand, EAP_AKA_RAND_LEN))
569                 goto parse_fail;
570
571         start = end + 1;
572         end = os_strchr(start, ' ');
573         if (end == NULL)
574                 goto parse_fail;
575         *end = '\0';
576         if (hexstr2bin(start, entry->u.aka.autn, EAP_AKA_AUTN_LEN))
577                 goto parse_fail;
578
579         start = end + 1;
580         end = os_strchr(start, ' ');
581         if (end == NULL)
582                 goto parse_fail;
583         *end = '\0';
584         if (hexstr2bin(start, entry->u.aka.ik, EAP_AKA_IK_LEN))
585                 goto parse_fail;
586
587         start = end + 1;
588         end = os_strchr(start, ' ');
589         if (end == NULL)
590                 goto parse_fail;
591         *end = '\0';
592         if (hexstr2bin(start, entry->u.aka.ck, EAP_AKA_CK_LEN))
593                 goto parse_fail;
594
595         start = end + 1;
596         end = os_strchr(start, ' ');
597         if (end)
598                 *end = '\0';
599         else {
600                 end = start;
601                 while (*end)
602                         end++;
603         }
604         entry->u.aka.res_len = (end - start) / 2;
605         if (entry->u.aka.res_len > EAP_AKA_RES_MAX_LEN) {
606                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: Too long RES");
607                 entry->u.aka.res_len = 0;
608                 goto parse_fail;
609         }
610         if (hexstr2bin(start, entry->u.aka.res, entry->u.aka.res_len))
611                 goto parse_fail;
612
613         entry->state = SUCCESS;
614         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
615                    "successfully - callback");
616         eap_sim_db_add_pending(data, entry);
617         data->get_complete_cb(data->ctx, entry->cb_session_ctx);
618         return;
619
620 parse_fail:
621         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
622         eap_sim_db_free_pending(data, entry);
623 }
624
625
626 static void eap_sim_db_receive(int sock, void *eloop_ctx, void *sock_ctx)
627 {
628         struct eap_sim_db_data *data = eloop_ctx;
629         char buf[1000], *pos, *cmd, *imsi;
630         int res;
631
632         res = recv(sock, buf, sizeof(buf) - 1, 0);
633         if (res < 0)
634                 return;
635         buf[res] = '\0';
636         wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-SIM DB: Received from an "
637                               "external source", (u8 *) buf, res);
638         if (res == 0)
639                 return;
640
641         if (data->get_complete_cb == NULL) {
642                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: No get_complete_cb "
643                            "registered");
644                 return;
645         }
646
647         /* <cmd> <IMSI> ... */
648
649         cmd = buf;
650         pos = os_strchr(cmd, ' ');
651         if (pos == NULL)
652                 goto parse_fail;
653         *pos = '\0';
654         imsi = pos + 1;
655         pos = os_strchr(imsi, ' ');
656         if (pos == NULL)
657                 goto parse_fail;
658         *pos = '\0';
659         wpa_printf(MSG_DEBUG, "EAP-SIM DB: External response=%s for IMSI %s",
660                    cmd, imsi);
661
662         if (os_strcmp(cmd, "SIM-RESP-AUTH") == 0)
663                 eap_sim_db_sim_resp_auth(data, imsi, pos + 1);
664         else if (os_strcmp(cmd, "AKA-RESP-AUTH") == 0)
665                 eap_sim_db_aka_resp_auth(data, imsi, pos + 1);
666         else
667                 wpa_printf(MSG_INFO, "EAP-SIM DB: Unknown external response "
668                            "'%s'", cmd);
669         return;
670
671 parse_fail:
672         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
673 }
674
675
676 static int eap_sim_db_open_socket(struct eap_sim_db_data *data)
677 {
678         struct sockaddr_un addr;
679         static int counter = 0;
680
681         if (os_strncmp(data->fname, "unix:", 5) != 0)
682                 return -1;
683
684         data->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
685         if (data->sock < 0) {
686                 wpa_printf(MSG_INFO, "socket(eap_sim_db): %s", strerror(errno));
687                 return -1;
688         }
689
690         os_memset(&addr, 0, sizeof(addr));
691         addr.sun_family = AF_UNIX;
692         os_snprintf(addr.sun_path, sizeof(addr.sun_path),
693                     "/tmp/eap_sim_db_%d-%d", getpid(), counter++);
694         os_free(data->local_sock);
695         data->local_sock = os_strdup(addr.sun_path);
696         if (data->local_sock == NULL) {
697                 close(data->sock);
698                 data->sock = -1;
699                 return -1;
700         }
701         if (bind(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
702                 wpa_printf(MSG_INFO, "bind(eap_sim_db): %s", strerror(errno));
703                 close(data->sock);
704                 data->sock = -1;
705                 return -1;
706         }
707
708         os_memset(&addr, 0, sizeof(addr));
709         addr.sun_family = AF_UNIX;
710         os_strlcpy(addr.sun_path, data->fname + 5, sizeof(addr.sun_path));
711         if (connect(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
712                 wpa_printf(MSG_INFO, "connect(eap_sim_db): %s",
713                            strerror(errno));
714                 wpa_hexdump_ascii(MSG_INFO, "HLR/AuC GW socket",
715                                   (u8 *) addr.sun_path,
716                                   os_strlen(addr.sun_path));
717                 close(data->sock);
718                 data->sock = -1;
719                 unlink(data->local_sock);
720                 os_free(data->local_sock);
721                 data->local_sock = NULL;
722                 return -1;
723         }
724
725         eloop_register_read_sock(data->sock, eap_sim_db_receive, data, NULL);
726
727         return 0;
728 }
729
730
731 static void eap_sim_db_close_socket(struct eap_sim_db_data *data)
732 {
733         if (data->sock >= 0) {
734                 eloop_unregister_read_sock(data->sock);
735                 close(data->sock);
736                 data->sock = -1;
737         }
738         if (data->local_sock) {
739                 unlink(data->local_sock);
740                 os_free(data->local_sock);
741                 data->local_sock = NULL;
742         }
743 }
744
745
746 /**
747  * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
748  * @config: Configuration data (e.g., file name)
749  * @db_timeout: Database lookup timeout
750  * @get_complete_cb: Callback function for reporting availability of triplets
751  * @ctx: Context pointer for get_complete_cb
752  * Returns: Pointer to a private data structure or %NULL on failure
753  */
754 struct eap_sim_db_data *
755 eap_sim_db_init(const char *config, unsigned int db_timeout,
756                 void (*get_complete_cb)(void *ctx, void *session_ctx),
757                 void *ctx)
758 {
759         struct eap_sim_db_data *data;
760         char *pos;
761
762         data = os_zalloc(sizeof(*data));
763         if (data == NULL)
764                 return NULL;
765
766         data->sock = -1;
767         data->get_complete_cb = get_complete_cb;
768         data->ctx = ctx;
769         data->eap_sim_db_timeout = db_timeout;
770         data->fname = os_strdup(config);
771         if (data->fname == NULL)
772                 goto fail;
773         pos = os_strstr(data->fname, " db=");
774         if (pos) {
775                 *pos = '\0';
776 #ifdef CONFIG_SQLITE
777                 pos += 4;
778                 data->sqlite_db = db_open(pos);
779                 if (data->sqlite_db == NULL)
780                         goto fail;
781 #endif /* CONFIG_SQLITE */
782         }
783
784         if (os_strncmp(data->fname, "unix:", 5) == 0) {
785                 if (eap_sim_db_open_socket(data)) {
786                         wpa_printf(MSG_DEBUG, "EAP-SIM DB: External database "
787                                    "connection not available - will retry "
788                                    "later");
789                 }
790         }
791
792         return data;
793
794 fail:
795         eap_sim_db_close_socket(data);
796         os_free(data->fname);
797         os_free(data);
798         return NULL;
799 }
800
801
802 static void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p)
803 {
804         os_free(p->permanent);
805         os_free(p->pseudonym);
806         os_free(p);
807 }
808
809
810 static void eap_sim_db_free_reauth(struct eap_sim_reauth *r)
811 {
812         os_free(r->permanent);
813         os_free(r->reauth_id);
814         os_free(r);
815 }
816
817
818 /**
819  * eap_sim_db_deinit - Deinitialize EAP-SIM DB/authentication gw interface
820  * @priv: Private data pointer from eap_sim_db_init()
821  */
822 void eap_sim_db_deinit(void *priv)
823 {
824         struct eap_sim_db_data *data = priv;
825         struct eap_sim_pseudonym *p, *prev;
826         struct eap_sim_reauth *r, *prevr;
827         struct eap_sim_db_pending *pending, *prev_pending;
828
829 #ifdef CONFIG_SQLITE
830         if (data->sqlite_db) {
831                 sqlite3_close(data->sqlite_db);
832                 data->sqlite_db = NULL;
833         }
834 #endif /* CONFIG_SQLITE */
835
836         eap_sim_db_close_socket(data);
837         os_free(data->fname);
838
839         p = data->pseudonyms;
840         while (p) {
841                 prev = p;
842                 p = p->next;
843                 eap_sim_db_free_pseudonym(prev);
844         }
845
846         r = data->reauths;
847         while (r) {
848                 prevr = r;
849                 r = r->next;
850                 eap_sim_db_free_reauth(prevr);
851         }
852
853         pending = data->pending;
854         while (pending) {
855                 prev_pending = pending;
856                 pending = pending->next;
857                 eap_sim_db_free_pending(data, prev_pending);
858         }
859
860         os_free(data);
861 }
862
863
864 static int eap_sim_db_send(struct eap_sim_db_data *data, const char *msg,
865                            size_t len)
866 {
867         int _errno = 0;
868
869         if (send(data->sock, msg, len, 0) < 0) {
870                 _errno = errno;
871                 wpa_printf(MSG_INFO, "send[EAP-SIM DB UNIX]: %s",
872                            strerror(errno));
873         }
874
875         if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
876             _errno == ECONNREFUSED) {
877                 /* Try to reconnect */
878                 eap_sim_db_close_socket(data);
879                 if (eap_sim_db_open_socket(data) < 0)
880                         return -1;
881                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: Reconnected to the "
882                            "external server");
883                 if (send(data->sock, msg, len, 0) < 0) {
884                         wpa_printf(MSG_INFO, "send[EAP-SIM DB UNIX]: %s",
885                                    strerror(errno));
886                         return -1;
887                 }
888         }
889
890         return 0;
891 }
892
893
894 static void eap_sim_db_expire_pending(struct eap_sim_db_data *data,
895                                       struct eap_sim_db_pending *entry)
896 {
897         eloop_register_timeout(data->eap_sim_db_timeout, 0,
898                                eap_sim_db_query_timeout, data, entry);
899 }
900
901
902 /**
903  * eap_sim_db_get_gsm_triplets - Get GSM triplets
904  * @data: Private data pointer from eap_sim_db_init()
905  * @username: Permanent username (prefix | IMSI)
906  * @max_chal: Maximum number of triplets
907  * @_rand: Buffer for RAND values
908  * @kc: Buffer for Kc values
909  * @sres: Buffer for SRES values
910  * @cb_session_ctx: Session callback context for get_complete_cb()
911  * Returns: Number of triplets received (has to be less than or equal to
912  * max_chal), -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not found), or
913  * -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this case, the
914  * callback function registered with eap_sim_db_init() will be called once the
915  * results become available.
916  *
917  * When using an external server for GSM triplets, this function can always
918  * start a request and return EAP_SIM_DB_PENDING immediately if authentication
919  * triplets are not available. Once the triplets are received, callback
920  * function registered with eap_sim_db_init() is called to notify EAP state
921  * machine to reprocess the message. This eap_sim_db_get_gsm_triplets()
922  * function will then be called again and the newly received triplets will then
923  * be given to the caller.
924  */
925 int eap_sim_db_get_gsm_triplets(struct eap_sim_db_data *data,
926                                 const char *username, int max_chal,
927                                 u8 *_rand, u8 *kc, u8 *sres,
928                                 void *cb_session_ctx)
929 {
930         struct eap_sim_db_pending *entry;
931         int len, ret;
932         char msg[40];
933         const char *imsi;
934         size_t imsi_len;
935
936         if (username == NULL || username[0] != EAP_SIM_PERMANENT_PREFIX ||
937             username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
938                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
939                            username);
940                 return EAP_SIM_DB_FAILURE;
941         }
942         imsi = username + 1;
943         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI '%s'",
944                    imsi);
945
946         entry = eap_sim_db_get_pending(data, imsi, 0);
947         if (entry) {
948                 int num_chal;
949                 if (entry->state == FAILURE) {
950                         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
951                                    "failure");
952                         eap_sim_db_free_pending(data, entry);
953                         return EAP_SIM_DB_FAILURE;
954                 }
955
956                 if (entry->state == PENDING) {
957                         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
958                                    "still pending");
959                         eap_sim_db_add_pending(data, entry);
960                         return EAP_SIM_DB_PENDING;
961                 }
962
963                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
964                            "%d challenges", entry->u.sim.num_chal);
965                 num_chal = entry->u.sim.num_chal;
966                 if (num_chal > max_chal)
967                         num_chal = max_chal;
968                 os_memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN);
969                 os_memcpy(sres, entry->u.sim.sres,
970                           num_chal * EAP_SIM_SRES_LEN);
971                 os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
972                 eap_sim_db_free_pending(data, entry);
973                 return num_chal;
974         }
975
976         if (data->sock < 0) {
977                 if (eap_sim_db_open_socket(data) < 0)
978                         return EAP_SIM_DB_FAILURE;
979         }
980
981         imsi_len = os_strlen(imsi);
982         len = os_snprintf(msg, sizeof(msg), "SIM-REQ-AUTH ");
983         if (os_snprintf_error(sizeof(msg), len) ||
984             len + imsi_len >= sizeof(msg))
985                 return EAP_SIM_DB_FAILURE;
986         os_memcpy(msg + len, imsi, imsi_len);
987         len += imsi_len;
988         ret = os_snprintf(msg + len, sizeof(msg) - len, " %d", max_chal);
989         if (os_snprintf_error(sizeof(msg) - len, ret))
990                 return EAP_SIM_DB_FAILURE;
991         len += ret;
992
993         wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting SIM authentication "
994                    "data for IMSI '%s'", imsi);
995         if (eap_sim_db_send(data, msg, len) < 0)
996                 return EAP_SIM_DB_FAILURE;
997
998         entry = os_zalloc(sizeof(*entry));
999         if (entry == NULL)
1000                 return EAP_SIM_DB_FAILURE;
1001
1002         os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
1003         entry->cb_session_ctx = cb_session_ctx;
1004         entry->state = PENDING;
1005         eap_sim_db_add_pending(data, entry);
1006         eap_sim_db_expire_pending(data, entry);
1007         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
1008
1009         return EAP_SIM_DB_PENDING;
1010 }
1011
1012
1013 static char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix)
1014 {
1015         char *id, *pos, *end;
1016         u8 buf[10];
1017
1018         if (random_get_bytes(buf, sizeof(buf)))
1019                 return NULL;
1020         id = os_malloc(sizeof(buf) * 2 + 2);
1021         if (id == NULL)
1022                 return NULL;
1023
1024         pos = id;
1025         end = id + sizeof(buf) * 2 + 2;
1026         *pos++ = prefix;
1027         wpa_snprintf_hex(pos, end - pos, buf, sizeof(buf));
1028         
1029         return id;
1030 }
1031
1032
1033 /**
1034  * eap_sim_db_get_next_pseudonym - EAP-SIM DB: Get next pseudonym
1035  * @data: Private data pointer from eap_sim_db_init()
1036  * @method: EAP method (SIM/AKA/AKA')
1037  * Returns: Next pseudonym (allocated string) or %NULL on failure
1038  *
1039  * This function is used to generate a pseudonym for EAP-SIM. The returned
1040  * pseudonym is not added to database at this point; it will need to be added
1041  * with eap_sim_db_add_pseudonym() once the authentication has been completed
1042  * successfully. Caller is responsible for freeing the returned buffer.
1043  */
1044 char * eap_sim_db_get_next_pseudonym(struct eap_sim_db_data *data,
1045                                      enum eap_sim_db_method method)
1046 {
1047         char prefix = EAP_SIM_REAUTH_ID_PREFIX;
1048
1049         switch (method) {
1050         case EAP_SIM_DB_SIM:
1051                 prefix = EAP_SIM_PSEUDONYM_PREFIX;
1052                 break;
1053         case EAP_SIM_DB_AKA:
1054                 prefix = EAP_AKA_PSEUDONYM_PREFIX;
1055                 break;
1056         case EAP_SIM_DB_AKA_PRIME:
1057                 prefix = EAP_AKA_PRIME_PSEUDONYM_PREFIX;
1058                 break;
1059         }
1060
1061         return eap_sim_db_get_next(data, prefix);
1062 }
1063
1064
1065 /**
1066  * eap_sim_db_get_next_reauth_id - EAP-SIM DB: Get next reauth_id
1067  * @data: Private data pointer from eap_sim_db_init()
1068  * @method: EAP method (SIM/AKA/AKA')
1069  * Returns: Next reauth_id (allocated string) or %NULL on failure
1070  *
1071  * This function is used to generate a fast re-authentication identity for
1072  * EAP-SIM. The returned reauth_id is not added to database at this point; it
1073  * will need to be added with eap_sim_db_add_reauth() once the authentication
1074  * has been completed successfully. Caller is responsible for freeing the
1075  * returned buffer.
1076  */
1077 char * eap_sim_db_get_next_reauth_id(struct eap_sim_db_data *data,
1078                                      enum eap_sim_db_method method)
1079 {
1080         char prefix = EAP_SIM_REAUTH_ID_PREFIX;
1081
1082         switch (method) {
1083         case EAP_SIM_DB_SIM:
1084                 prefix = EAP_SIM_REAUTH_ID_PREFIX;
1085                 break;
1086         case EAP_SIM_DB_AKA:
1087                 prefix = EAP_AKA_REAUTH_ID_PREFIX;
1088                 break;
1089         case EAP_SIM_DB_AKA_PRIME:
1090                 prefix = EAP_AKA_PRIME_REAUTH_ID_PREFIX;
1091                 break;
1092         }
1093
1094         return eap_sim_db_get_next(data, prefix);
1095 }
1096
1097
1098 /**
1099  * eap_sim_db_add_pseudonym - EAP-SIM DB: Add new pseudonym
1100  * @data: Private data pointer from eap_sim_db_init()
1101  * @permanent: Permanent username
1102  * @pseudonym: Pseudonym for this user. This needs to be an allocated buffer,
1103  * e.g., return value from eap_sim_db_get_next_pseudonym(). Caller must not
1104  * free it.
1105  * Returns: 0 on success, -1 on failure
1106  *
1107  * This function adds a new pseudonym for EAP-SIM user. EAP-SIM DB is
1108  * responsible of freeing pseudonym buffer once it is not needed anymore.
1109  */
1110 int eap_sim_db_add_pseudonym(struct eap_sim_db_data *data,
1111                              const char *permanent, char *pseudonym)
1112 {
1113         struct eap_sim_pseudonym *p;
1114         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add pseudonym '%s' for permanent "
1115                    "username '%s'", pseudonym, permanent);
1116
1117         /* TODO: could store last two pseudonyms */
1118 #ifdef CONFIG_SQLITE
1119         if (data->sqlite_db)
1120                 return db_add_pseudonym(data, permanent, pseudonym);
1121 #endif /* CONFIG_SQLITE */
1122         for (p = data->pseudonyms; p; p = p->next) {
1123                 if (os_strcmp(permanent, p->permanent) == 0)
1124                         break;
1125         }
1126         if (p) {
1127                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
1128                            "pseudonym: %s", p->pseudonym);
1129                 os_free(p->pseudonym);
1130                 p->pseudonym = pseudonym;
1131                 return 0;
1132         }
1133
1134         p = os_zalloc(sizeof(*p));
1135         if (p == NULL) {
1136                 os_free(pseudonym);
1137                 return -1;
1138         }
1139
1140         p->next = data->pseudonyms;
1141         p->permanent = os_strdup(permanent);
1142         if (p->permanent == NULL) {
1143                 os_free(p);
1144                 os_free(pseudonym);
1145                 return -1;
1146         }
1147         p->pseudonym = pseudonym;
1148         data->pseudonyms = p;
1149
1150         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new pseudonym entry");
1151         return 0;
1152 }
1153
1154
1155 static struct eap_sim_reauth *
1156 eap_sim_db_add_reauth_data(struct eap_sim_db_data *data,
1157                            const char *permanent,
1158                            char *reauth_id, u16 counter)
1159 {
1160         struct eap_sim_reauth *r;
1161
1162         for (r = data->reauths; r; r = r->next) {
1163                 if (os_strcmp(r->permanent, permanent) == 0)
1164                         break;
1165         }
1166
1167         if (r) {
1168                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
1169                            "reauth_id: %s", r->reauth_id);
1170                 os_free(r->reauth_id);
1171                 r->reauth_id = reauth_id;
1172         } else {
1173                 r = os_zalloc(sizeof(*r));
1174                 if (r == NULL) {
1175                         os_free(reauth_id);
1176                         return NULL;
1177                 }
1178
1179                 r->next = data->reauths;
1180                 r->permanent = os_strdup(permanent);
1181                 if (r->permanent == NULL) {
1182                         os_free(r);
1183                         os_free(reauth_id);
1184                         return NULL;
1185                 }
1186                 r->reauth_id = reauth_id;
1187                 data->reauths = r;
1188                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new reauth entry");
1189         }
1190
1191         r->counter = counter;
1192
1193         return r;
1194 }
1195
1196
1197 /**
1198  * eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry
1199  * @priv: Private data pointer from eap_sim_db_init()
1200  * @permanent: Permanent username
1201  * @identity_len: Length of identity
1202  * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
1203  * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
1204  * free it.
1205  * @counter: AT_COUNTER value for fast re-authentication
1206  * @mk: 16-byte MK from the previous full authentication or %NULL
1207  * Returns: 0 on success, -1 on failure
1208  *
1209  * This function adds a new re-authentication entry for an EAP-SIM user.
1210  * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
1211  * anymore.
1212  */
1213 int eap_sim_db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
1214                           char *reauth_id, u16 counter, const u8 *mk)
1215 {
1216         struct eap_sim_reauth *r;
1217
1218         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
1219                    "identity '%s'", reauth_id, permanent);
1220
1221 #ifdef CONFIG_SQLITE
1222         if (data->sqlite_db)
1223                 return db_add_reauth(data, permanent, reauth_id, counter, mk,
1224                                      NULL, NULL, NULL);
1225 #endif /* CONFIG_SQLITE */
1226         r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
1227         if (r == NULL)
1228                 return -1;
1229
1230         os_memcpy(r->mk, mk, EAP_SIM_MK_LEN);
1231
1232         return 0;
1233 }
1234
1235
1236 #ifdef EAP_SERVER_AKA_PRIME
1237 /**
1238  * eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry
1239  * @data: Private data pointer from eap_sim_db_init()
1240  * @permanent: Permanent username
1241  * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
1242  * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
1243  * free it.
1244  * @counter: AT_COUNTER value for fast re-authentication
1245  * @k_encr: K_encr from the previous full authentication
1246  * @k_aut: K_aut from the previous full authentication
1247  * @k_re: 32-byte K_re from the previous full authentication
1248  * Returns: 0 on success, -1 on failure
1249  *
1250  * This function adds a new re-authentication entry for an EAP-AKA' user.
1251  * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
1252  * anymore.
1253  */
1254 int eap_sim_db_add_reauth_prime(struct eap_sim_db_data *data,
1255                                 const char *permanent, char *reauth_id,
1256                                 u16 counter, const u8 *k_encr,
1257                                 const u8 *k_aut, const u8 *k_re)
1258 {
1259         struct eap_sim_reauth *r;
1260
1261         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
1262                    "identity '%s'", reauth_id, permanent);
1263
1264 #ifdef CONFIG_SQLITE
1265         if (data->sqlite_db)
1266                 return db_add_reauth(data, permanent, reauth_id, counter, NULL,
1267                                      k_encr, k_aut, k_re);
1268 #endif /* CONFIG_SQLITE */
1269         r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
1270         if (r == NULL)
1271                 return -1;
1272
1273         os_memcpy(r->k_encr, k_encr, EAP_SIM_K_ENCR_LEN);
1274         os_memcpy(r->k_aut, k_aut, EAP_AKA_PRIME_K_AUT_LEN);
1275         os_memcpy(r->k_re, k_re, EAP_AKA_PRIME_K_RE_LEN);
1276
1277         return 0;
1278 }
1279 #endif /* EAP_SERVER_AKA_PRIME */
1280
1281
1282 /**
1283  * eap_sim_db_get_permanent - EAP-SIM DB: Get permanent identity
1284  * @data: Private data pointer from eap_sim_db_init()
1285  * @pseudonym: Pseudonym username
1286  * Returns: Pointer to permanent username or %NULL if not found
1287  */
1288 const char *
1289 eap_sim_db_get_permanent(struct eap_sim_db_data *data, const char *pseudonym)
1290 {
1291         struct eap_sim_pseudonym *p;
1292
1293 #ifdef CONFIG_SQLITE
1294         if (data->sqlite_db)
1295                 return db_get_pseudonym(data, pseudonym);
1296 #endif /* CONFIG_SQLITE */
1297
1298         p = data->pseudonyms;
1299         while (p) {
1300                 if (os_strcmp(p->pseudonym, pseudonym) == 0)
1301                         return p->permanent;
1302                 p = p->next;
1303         }
1304
1305         return NULL;
1306 }
1307
1308
1309 /**
1310  * eap_sim_db_get_reauth_entry - EAP-SIM DB: Get re-authentication entry
1311  * @data: Private data pointer from eap_sim_db_init()
1312  * @reauth_id: Fast re-authentication username
1313  * Returns: Pointer to the re-auth entry, or %NULL if not found
1314  */
1315 struct eap_sim_reauth *
1316 eap_sim_db_get_reauth_entry(struct eap_sim_db_data *data,
1317                             const char *reauth_id)
1318 {
1319         struct eap_sim_reauth *r;
1320
1321 #ifdef CONFIG_SQLITE
1322         if (data->sqlite_db)
1323                 return db_get_reauth(data, reauth_id);
1324 #endif /* CONFIG_SQLITE */
1325
1326         r = data->reauths;
1327         while (r) {
1328                 if (os_strcmp(r->reauth_id, reauth_id) == 0)
1329                         break;
1330                 r = r->next;
1331         }
1332
1333         return r;
1334 }
1335
1336
1337 /**
1338  * eap_sim_db_remove_reauth - EAP-SIM DB: Remove re-authentication entry
1339  * @data: Private data pointer from eap_sim_db_init()
1340  * @reauth: Pointer to re-authentication entry from
1341  * eap_sim_db_get_reauth_entry()
1342  */
1343 void eap_sim_db_remove_reauth(struct eap_sim_db_data *data,
1344                               struct eap_sim_reauth *reauth)
1345 {
1346         struct eap_sim_reauth *r, *prev = NULL;
1347 #ifdef CONFIG_SQLITE
1348         if (data->sqlite_db) {
1349                 db_remove_reauth(data, reauth);
1350                 return;
1351         }
1352 #endif /* CONFIG_SQLITE */
1353         r = data->reauths;
1354         while (r) {
1355                 if (r == reauth) {
1356                         if (prev)
1357                                 prev->next = r->next;
1358                         else
1359                                 data->reauths = r->next;
1360                         eap_sim_db_free_reauth(r);
1361                         return;
1362                 }
1363                 prev = r;
1364                 r = r->next;
1365         }
1366 }
1367
1368
1369 /**
1370  * eap_sim_db_get_aka_auth - Get AKA authentication values
1371  * @data: Private data pointer from eap_sim_db_init()
1372  * @username: Permanent username (prefix | IMSI)
1373  * @_rand: Buffer for RAND value
1374  * @autn: Buffer for AUTN value
1375  * @ik: Buffer for IK value
1376  * @ck: Buffer for CK value
1377  * @res: Buffer for RES value
1378  * @res_len: Buffer for RES length
1379  * @cb_session_ctx: Session callback context for get_complete_cb()
1380  * Returns: 0 on success, -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not
1381  * found), or -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this
1382  * case, the callback function registered with eap_sim_db_init() will be
1383  * called once the results become available.
1384  *
1385  * When using an external server for AKA authentication, this function can
1386  * always start a request and return EAP_SIM_DB_PENDING immediately if
1387  * authentication triplets are not available. Once the authentication data are
1388  * received, callback function registered with eap_sim_db_init() is called to
1389  * notify EAP state machine to reprocess the message. This
1390  * eap_sim_db_get_aka_auth() function will then be called again and the newly
1391  * received triplets will then be given to the caller.
1392  */
1393 int eap_sim_db_get_aka_auth(struct eap_sim_db_data *data, const char *username,
1394                             u8 *_rand, u8 *autn, u8 *ik, u8 *ck,
1395                             u8 *res, size_t *res_len, void *cb_session_ctx)
1396 {
1397         struct eap_sim_db_pending *entry;
1398         int len;
1399         char msg[40];
1400         const char *imsi;
1401         size_t imsi_len;
1402
1403         if (username == NULL ||
1404             (username[0] != EAP_AKA_PERMANENT_PREFIX &&
1405              username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
1406             username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
1407                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
1408                            username);
1409                 return EAP_SIM_DB_FAILURE;
1410         }
1411         imsi = username + 1;
1412         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
1413                    imsi);
1414
1415         entry = eap_sim_db_get_pending(data, imsi, 1);
1416         if (entry) {
1417                 if (entry->state == FAILURE) {
1418                         eap_sim_db_free_pending(data, entry);
1419                         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
1420                         return EAP_SIM_DB_FAILURE;
1421                 }
1422
1423                 if (entry->state == PENDING) {
1424                         eap_sim_db_add_pending(data, entry);
1425                         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending");
1426                         return EAP_SIM_DB_PENDING;
1427                 }
1428
1429                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: Returning successfully "
1430                            "received authentication data");
1431                 os_memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN);
1432                 os_memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN);
1433                 os_memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN);
1434                 os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
1435                 os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
1436                 *res_len = entry->u.aka.res_len;
1437                 eap_sim_db_free_pending(data, entry);
1438                 return 0;
1439         }
1440
1441         if (data->sock < 0) {
1442                 if (eap_sim_db_open_socket(data) < 0)
1443                         return EAP_SIM_DB_FAILURE;
1444         }
1445
1446         imsi_len = os_strlen(imsi);
1447         len = os_snprintf(msg, sizeof(msg), "AKA-REQ-AUTH ");
1448         if (os_snprintf_error(sizeof(msg), len) ||
1449             len + imsi_len >= sizeof(msg))
1450                 return EAP_SIM_DB_FAILURE;
1451         os_memcpy(msg + len, imsi, imsi_len);
1452         len += imsi_len;
1453
1454         wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting AKA authentication "
1455                     "data for IMSI '%s'", imsi);
1456         if (eap_sim_db_send(data, msg, len) < 0)
1457                 return EAP_SIM_DB_FAILURE;
1458
1459         entry = os_zalloc(sizeof(*entry));
1460         if (entry == NULL)
1461                 return EAP_SIM_DB_FAILURE;
1462
1463         entry->aka = 1;
1464         os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
1465         entry->cb_session_ctx = cb_session_ctx;
1466         entry->state = PENDING;
1467         eap_sim_db_add_pending(data, entry);
1468         eap_sim_db_expire_pending(data, entry);
1469         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
1470
1471         return EAP_SIM_DB_PENDING;
1472 }
1473
1474
1475 /**
1476  * eap_sim_db_resynchronize - Resynchronize AKA AUTN
1477  * @data: Private data pointer from eap_sim_db_init()
1478  * @username: Permanent username
1479  * @auts: AUTS value from the peer
1480  * @_rand: RAND value used in the rejected message
1481  * Returns: 0 on success, -1 on failure
1482  *
1483  * This function is called when the peer reports synchronization failure in the
1484  * AUTN value by sending AUTS. The AUTS and RAND values should be sent to
1485  * HLR/AuC to allow it to resynchronize with the peer. After this,
1486  * eap_sim_db_get_aka_auth() will be called again to to fetch updated
1487  * RAND/AUTN values for the next challenge.
1488  */
1489 int eap_sim_db_resynchronize(struct eap_sim_db_data *data,
1490                              const char *username,
1491                              const u8 *auts, const u8 *_rand)
1492 {
1493         const char *imsi;
1494         size_t imsi_len;
1495
1496         if (username == NULL ||
1497             (username[0] != EAP_AKA_PERMANENT_PREFIX &&
1498              username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
1499             username[1] == '\0' || os_strlen(username) > 20) {
1500                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
1501                            username);
1502                 return -1;
1503         }
1504         imsi = username + 1;
1505         wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
1506                    imsi);
1507
1508         if (data->sock >= 0) {
1509                 char msg[100];
1510                 int len, ret;
1511
1512                 imsi_len = os_strlen(imsi);
1513                 len = os_snprintf(msg, sizeof(msg), "AKA-AUTS ");
1514                 if (os_snprintf_error(sizeof(msg), len) ||
1515                     len + imsi_len >= sizeof(msg))
1516                         return -1;
1517                 os_memcpy(msg + len, imsi, imsi_len);
1518                 len += imsi_len;
1519
1520                 ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
1521                 if (os_snprintf_error(sizeof(msg) - len, ret))
1522                         return -1;
1523                 len += ret;
1524                 len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
1525                                         auts, EAP_AKA_AUTS_LEN);
1526                 ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
1527                 if (os_snprintf_error(sizeof(msg) - len, ret))
1528                         return -1;
1529                 len += ret;
1530                 len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
1531                                         _rand, EAP_AKA_RAND_LEN);
1532                 wpa_printf(MSG_DEBUG, "EAP-SIM DB: reporting AKA AUTS for "
1533                            "IMSI '%s'", imsi);
1534                 if (eap_sim_db_send(data, msg, len) < 0)
1535                         return -1;
1536         }
1537
1538         return 0;
1539 }
1540
1541
1542 /**
1543  * sim_get_username - Extract username from SIM identity
1544  * @identity: Identity
1545  * @identity_len: Identity length
1546  * Returns: Allocated buffer with the username part of the identity
1547  *
1548  * Caller is responsible for freeing the returned buffer with os_free().
1549  */
1550 char * sim_get_username(const u8 *identity, size_t identity_len)
1551 {
1552         size_t pos;
1553
1554         if (identity == NULL)
1555                 return NULL;
1556
1557         for (pos = 0; pos < identity_len; pos++) {
1558                 if (identity[pos] == '@' || identity[pos] == '\0')
1559                         break;
1560         }
1561
1562         return dup_binstr(identity, pos);
1563 }