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