diff options
-rw-r--r-- | hostapd/hlr_auc_gw.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c index 8b7455f..91772a6 100644 --- a/hostapd/hlr_auc_gw.c +++ b/hostapd/hlr_auc_gw.c @@ -1,6 +1,6 @@ /* * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator - * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> + * Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -47,6 +47,9 @@ static const char *default_socket_path = "/tmp/hlr_auc_gw.sock"; static const char *socket_path; static int serv_sock = -1; +static char *milenage_file = NULL; +static int update_milenage = 0; +static int sqn_changes = 0; /* GSM triplets */ struct gsm_triplet { @@ -368,6 +371,80 @@ static int read_milenage(const char *fname) } +static void update_milenage_file(const char *fname) +{ + FILE *f, *f2; + char buf[500], *pos; + char *end = buf + sizeof(buf); + struct milenage_parameters *m; + size_t imsi_len; + + f = fopen(fname, "r"); + if (f == NULL) { + printf("Could not open Milenage data file '%s'\n", fname); + return; + } + + snprintf(buf, sizeof(buf), "%s.new", fname); + f2 = fopen(buf, "w"); + if (f2 == NULL) { + printf("Could not write Milenage data file '%s'\n", buf); + fclose(f); + return; + } + + while (fgets(buf, sizeof(buf), f)) { + /* IMSI Ki OPc AMF SQN */ + buf[sizeof(buf) - 1] = '\0'; + + pos = strchr(buf, ' '); + if (buf[0] == '#' || pos == NULL || pos - buf >= 20) + goto no_update; + + imsi_len = pos - buf; + + for (m = milenage_db; m; m = m->next) { + if (strncmp(buf, m->imsi, imsi_len) == 0 && + m->imsi[imsi_len] == '\0') + break; + } + + if (!m) + goto no_update; + + pos = buf; + pos += snprintf(pos, end - pos, "%s ", m->imsi); + pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16); + *pos++ = ' '; + pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16); + *pos++ = ' '; + pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2); + *pos++ = ' '; + pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6); + *pos++ = '\n'; + + no_update: + fprintf(f2, "%s", buf); + } + + fclose(f2); + fclose(f); + + snprintf(buf, sizeof(buf), "%s.bak", fname); + if (rename(fname, buf) < 0) { + perror("rename"); + return; + } + + snprintf(buf, sizeof(buf), "%s.new", fname); + if (rename(buf, fname) < 0) { + perror("rename"); + return; + } + +} + + static struct milenage_parameters * get_milenage(const char *imsi) { struct milenage_parameters *m = milenage_db; @@ -480,6 +557,7 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen, return; res_len = EAP_AKA_RES_MAX_LEN; inc_byte_array(m->sqn, 6); + sqn_changes = 1; printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n", m->sqn[0], m->sqn[1], m->sqn[2], m->sqn[3], m->sqn[4], m->sqn[5]); @@ -563,6 +641,7 @@ static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen, printf("AKA-AUTS: Re-synchronized: " "SQN=%02x%02x%02x%02x%02x%02x\n", sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]); + sqn_changes = 1; } } @@ -609,6 +688,9 @@ static void cleanup(void) struct gsm_triplet *g, *gprev; struct milenage_parameters *m, *prev; + if (update_milenage && milenage_file && sqn_changes) + update_milenage_file(milenage_file); + g = gsm_db; while (g) { gprev = g; @@ -639,14 +721,15 @@ static void usage(void) { printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA " "database/authenticator\n" - "Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>\n" + "Copyright (c) 2005-2007, 2012, Jouni Malinen <j@w1.fi>\n" "\n" "usage:\n" - "hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] " + "hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] " "[-m<milenage file>]\n" "\n" "options:\n" " -h = show this usage help\n" + " -u = update SQN in Milenage file on exit\n" " -s<socket path> = path for UNIX domain socket\n" " (default: %s)\n" " -g<triplet file> = path for GSM authentication triplets\n" @@ -658,7 +741,6 @@ static void usage(void) int main(int argc, char *argv[]) { int c; - char *milenage_file = NULL; char *gsm_triplet_file = NULL; if (os_program_init()) @@ -667,7 +749,7 @@ int main(int argc, char *argv[]) socket_path = default_socket_path; for (;;) { - c = getopt(argc, argv, "g:hm:s:"); + c = getopt(argc, argv, "g:hm:s:u"); if (c < 0) break; switch (c) { @@ -683,6 +765,9 @@ int main(int argc, char *argv[]) case 's': socket_path = optarg; break; + case 'u': + update_milenage = 1; + break; default: usage(); return -1; |