📄 hlr_auc_gw.c
字号:
/* * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This is an example implementation of the EAP-SIM/AKA database/authentication * gateway interface to HLR/AuC. It is expected to be replaced with an * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or * a local implementation of SIM triplet and AKA authentication data generator. * * hostapd will send SIM/AKA authentication queries over a UNIX domain socket * to and external program, e.g., this hlr_auc_gw. This interface uses simple * text-based format: * * EAP-SIM / GSM triplet query/response: * SIM-REQ-AUTH <IMSI> <max_chal> * SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3] * SIM-RESP-AUTH <IMSI> FAILURE * * EAP-AKA / UMTS query/response: * AKA-REQ-AUTH <IMSI> * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> * AKA-RESP-AUTH <IMSI> FAILURE * * EAP-AKA / UMTS AUTS (re-synchronization): * AKA-AUTS <IMSI> <AUTS> <RAND> * * IMSI and max_chal are sent as an ASCII string, * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings. * * The example implementation here reads GSM authentication triplets from a * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex * strings. This is used to simulate an HLR/AuC. As such, it is not very useful * for real life authentication, but it is useful both as an example * implementation and for EAP-SIM testing. */#include "includes.h"#include <sys/un.h>#include "common.h"#include "milenage.h"static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";static const char *socket_path;static int serv_sock = -1;/* GSM triplets */struct gsm_triplet { struct gsm_triplet *next; char imsi[20]; u8 kc[8]; u8 sres[4]; u8 _rand[16];};static struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL;/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */struct milenage_parameters { struct milenage_parameters *next; char imsi[20]; u8 ki[16]; u8 opc[16]; u8 amf[2]; u8 sqn[6];};static struct milenage_parameters *milenage_db = NULL;#define EAP_SIM_MAX_CHAL 3#define EAP_AKA_RAND_LEN 16#define EAP_AKA_AUTN_LEN 16#define EAP_AKA_AUTS_LEN 14#define EAP_AKA_RES_MAX_LEN 16#define EAP_AKA_IK_LEN 16#define EAP_AKA_CK_LEN 16static int open_socket(const char *path){ struct sockaddr_un addr; int s; s = socket(PF_UNIX, SOCK_DGRAM, 0); if (s < 0) { perror("socket(PF_UNIX)"); return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind(PF_UNIX)"); close(s); return -1; } return s;}static int read_gsm_triplets(const char *fname){ FILE *f; char buf[200], *pos, *pos2; struct gsm_triplet *g = NULL; int line, ret = 0; if (fname == NULL) return -1; f = fopen(fname, "r"); if (f == NULL) { printf("Could not open GSM tripler data file '%s'\n", fname); return -1; } line = 0; while (fgets(buf, sizeof(buf), f)) { line++; /* Parse IMSI:Kc:SRES:RAND */ buf[sizeof(buf) - 1] = '\0'; if (buf[0] == '#') continue; pos = buf; while (*pos != '\0' && *pos != '\n') pos++; if (*pos == '\n') *pos = '\0'; pos = buf; if (*pos == '\0') continue; g = os_zalloc(sizeof(*g)); if (g == NULL) { ret = -1; break; } /* IMSI */ pos2 = strchr(pos, ':'); if (pos2 == NULL) { printf("%s:%d - Invalid IMSI (%s)\n", fname, line, pos); ret = -1; break; } *pos2 = '\0'; if (strlen(pos) >= sizeof(g->imsi)) { printf("%s:%d - Too long IMSI (%s)\n", fname, line, pos); ret = -1; break; } os_strlcpy(g->imsi, pos, sizeof(g->imsi)); pos = pos2 + 1; /* Kc */ pos2 = strchr(pos, ':'); if (pos2 == NULL) { printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos); ret = -1; break; } *pos2 = '\0'; if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) { printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos); ret = -1; break; } pos = pos2 + 1; /* SRES */ pos2 = strchr(pos, ':'); if (pos2 == NULL) { printf("%s:%d - Invalid SRES (%s)\n", fname, line, pos); ret = -1; break; } *pos2 = '\0'; if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) { printf("%s:%d - Invalid SRES (%s)\n", fname, line, pos); ret = -1; break; } pos = pos2 + 1; /* RAND */ pos2 = strchr(pos, ':'); if (pos2) *pos2 = '\0'; if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) { printf("%s:%d - Invalid RAND (%s)\n", fname, line, pos); ret = -1; break; } pos = pos2 + 1; g->next = gsm_db; gsm_db = g; g = NULL; } free(g); fclose(f); return ret;}static struct gsm_triplet * get_gsm_triplet(const char *imsi){ struct gsm_triplet *g = gsm_db_pos; while (g) { if (strcmp(g->imsi, imsi) == 0) { gsm_db_pos = g->next; return g; } g = g->next; } g = gsm_db; while (g && g != gsm_db_pos) { if (strcmp(g->imsi, imsi) == 0) { gsm_db_pos = g->next; return g; } g = g->next; } return NULL;}static int read_milenage(const char *fname){ FILE *f; char buf[200], *pos, *pos2; struct milenage_parameters *m = NULL; int line, ret = 0; if (fname == NULL) return -1; f = fopen(fname, "r"); if (f == NULL) { printf("Could not open Milenage data file '%s'\n", fname); return -1; } line = 0; while (fgets(buf, sizeof(buf), f)) { line++; /* Parse IMSI Ki OPc AMF SQN */ buf[sizeof(buf) - 1] = '\0'; if (buf[0] == '#') continue; pos = buf; while (*pos != '\0' && *pos != '\n') pos++; if (*pos == '\n') *pos = '\0'; pos = buf; if (*pos == '\0') continue; m = os_zalloc(sizeof(*m)); if (m == NULL) { ret = -1; break; } /* IMSI */ pos2 = strchr(pos, ' '); if (pos2 == NULL) { printf("%s:%d - Invalid IMSI (%s)\n", fname, line, pos); ret = -1; break; } *pos2 = '\0'; if (strlen(pos) >= sizeof(m->imsi)) { printf("%s:%d - Too long IMSI (%s)\n", fname, line, pos); ret = -1; break; } os_strlcpy(m->imsi, pos, sizeof(m->imsi)); pos = pos2 + 1; /* Ki */ pos2 = strchr(pos, ' '); if (pos2 == NULL) { printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos); ret = -1; break; } *pos2 = '\0'; if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) { printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos); ret = -1; break; } pos = pos2 + 1; /* OPc */ pos2 = strchr(pos, ' '); if (pos2 == NULL) { printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos); ret = -1; break; } *pos2 = '\0'; if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) { printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos); ret = -1; break; } pos = pos2 + 1; /* AMF */ pos2 = strchr(pos, ' '); if (pos2 == NULL) { printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos); ret = -1; break; } *pos2 = '\0'; if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) { printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos); ret = -1; break; } pos = pos2 + 1; /* SQN */ pos2 = strchr(pos, ' '); if (pos2) *pos2 = '\0'; if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) { printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -