X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=hostapd%2Fhlr_auc_gw.c;h=5caa779dd648b0315818f23852257aee26577247;hb=a36e13a7cd1277c8bb64b8dbcc7def5d7009d6fa;hp=2e61ac3906212e2f48991d62b4301c861222ffa9;hpb=77e3094bb73d9765461e3cc0480ae449f275daff;p=thirdparty%2Fhostap.git diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c index 2e61ac390..5caa779dd 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, 2012-2013, Jouni Malinen + * Copyright (c) 2005-2007, 2012-2017, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -18,6 +18,9 @@ * SIM-REQ-AUTH * SIM-RESP-AUTH Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3] * SIM-RESP-AUTH FAILURE + * GSM-AUTH-REQ RAND1:RAND2[:RAND3] + * GSM-AUTH-RESP Kc1:SRES1:Kc2:SRES2[:Kc3:SRES3] + * GSM-AUTH-RESP FAILURE * * EAP-AKA / UMTS query/response: * AKA-REQ-AUTH @@ -84,6 +87,7 @@ struct milenage_parameters { u8 amf[2]; u8 sqn[6]; int set; + size_t res_len; }; static struct milenage_parameters *milenage_db = NULL; @@ -93,6 +97,7 @@ static struct milenage_parameters *milenage_db = NULL; #define EAP_AKA_RAND_LEN 16 #define EAP_AKA_AUTN_LEN 16 #define EAP_AKA_AUTS_LEN 14 +#define EAP_AKA_RES_MIN_LEN 4 #define EAP_AKA_RES_MAX_LEN 16 #define EAP_AKA_IK_LEN 16 #define EAP_AKA_CK_LEN 16 @@ -121,7 +126,8 @@ static int db_table_create_milenage(sqlite3 *db) " ki CHAR(32) NOT NULL," " opc CHAR(32) NOT NULL," " amf CHAR(4) NOT NULL," - " sqn CHAR(12) NOT NULL" + " sqn CHAR(12) NOT NULL," + " res_len INTEGER" ");"; printf("Adding database table for milenage information\n"); @@ -187,6 +193,10 @@ static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[]) printf("Invalid sqn value in database\n"); return -1; } + + if (os_strcmp(col[i], "res_len") == 0 && argv[i]) { + m->res_len = atoi(argv[i]); + } } return 0; @@ -203,8 +213,7 @@ static struct milenage_parameters * db_get_milenage(const char *imsi_txt) os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi), "%llu", imsi); os_snprintf(cmd, sizeof(cmd), - "SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;", - imsi); + "SELECT * FROM milenage WHERE imsi=%llu;", imsi); if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage, NULL) != SQLITE_OK) return NULL; @@ -275,7 +284,7 @@ static int read_gsm_triplets(const char *fname) f = fopen(fname, "r"); if (f == NULL) { - printf("Could not open GSM tripler data file '%s'\n", fname); + printf("Could not open GSM triplet data file '%s'\n", fname); return -1; } @@ -303,66 +312,40 @@ static int read_gsm_triplets(const char *fname) } /* 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); + pos2 = NULL; + pos = str_token(buf, ":", &pos2); + if (!pos || os_strlen(pos) >= sizeof(g->imsi)) { + printf("%s:%d - Invalid IMSI\n", fname, line); 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); + pos = str_token(buf, ":", &pos2); + if (!pos || os_strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) { + printf("%s:%d - Invalid Kc\n", fname, line); 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); + pos = str_token(buf, ":", &pos2); + if (!pos || os_strlen(pos) != 8 || + hexstr2bin(pos, g->sres, 4)) { + printf("%s:%d - Invalid SRES\n", fname, line); 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); + pos = str_token(buf, ":", &pos2); + if (!pos || os_strlen(pos) != 32 || + hexstr2bin(pos, g->_rand, 16)) { + printf("%s:%d - Invalid RAND\n", fname, line); ret = -1; break; } - pos = pos2 + 1; g->next = gsm_db; gsm_db = g; @@ -421,7 +404,7 @@ static int read_milenage(const char *fname) while (fgets(buf, sizeof(buf), f)) { line++; - /* Parse IMSI Ki OPc AMF SQN */ + /* Parse IMSI Ki OPc AMF SQN [RES_len] */ buf[sizeof(buf) - 1] = '\0'; if (buf[0] == '#') continue; @@ -441,78 +424,62 @@ static int read_milenage(const char *fname) } /* 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); + pos2 = NULL; + pos = str_token(buf, " ", &pos2); + if (!pos || os_strlen(pos) >= sizeof(m->imsi)) { + printf("%s:%d - Invalid IMSI\n", fname, line); 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); + pos = str_token(buf, " ", &pos2); + if (!pos || os_strlen(pos) != 32 || + hexstr2bin(pos, m->ki, 16)) { + printf("%s:%d - Invalid Ki\n", fname, line); 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); + pos = str_token(buf, " ", &pos2); + if (!pos || os_strlen(pos) != 32 || + hexstr2bin(pos, m->opc, 16)) { + printf("%s:%d - Invalid OPc\n", fname, line); 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); + pos = str_token(buf, " ", &pos2); + if (!pos || os_strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) { + printf("%s:%d - Invalid AMF\n", fname, line); 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); + pos = str_token(buf, " ", &pos2); + if (!pos || os_strlen(pos) != 12 || + hexstr2bin(pos, m->sqn, 6)) { + printf("%s:%d - Invalid SEQ\n", fname, line); ret = -1; break; } - pos = pos2 + 1; + + pos = str_token(buf, " ", &pos2); + if (pos) { + m->res_len = atoi(pos); + if (m->res_len && + (m->res_len < EAP_AKA_RES_MIN_LEN || + m->res_len > EAP_AKA_RES_MAX_LEN)) { + printf("%s:%d - Invalid RES_len\n", + fname, line); + ret = -1; + break; + } + } m->next = milenage_db; milenage_db = m; @@ -529,7 +496,7 @@ static int read_milenage(const char *fname) static void update_milenage_file(const char *fname) { FILE *f, *f2; - char buf[500], *pos; + char name[500], buf[500], *pos; char *end = buf + sizeof(buf); struct milenage_parameters *m; size_t imsi_len; @@ -540,10 +507,10 @@ static void update_milenage_file(const char *fname) return; } - snprintf(buf, sizeof(buf), "%s.new", fname); - f2 = fopen(buf, "w"); + snprintf(name, sizeof(name), "%s.new", fname); + f2 = fopen(name, "w"); if (f2 == NULL) { - printf("Could not write Milenage data file '%s'\n", buf); + printf("Could not write Milenage data file '%s'\n", name); fclose(f); return; } @@ -585,14 +552,14 @@ static void update_milenage_file(const char *fname) fclose(f2); fclose(f); - snprintf(buf, sizeof(buf), "%s.bak", fname); - if (rename(fname, buf) < 0) { + snprintf(name, sizeof(name), "%s.bak", fname); + if (rename(fname, name) < 0) { perror("rename"); return; } - snprintf(buf, sizeof(buf), "%s.new", fname); - if (rename(buf, fname) < 0) { + snprintf(name, sizeof(name), "%s.new", fname); + if (rename(name, fname) < 0) { perror("rename"); return; } @@ -692,6 +659,56 @@ static int sim_req_auth(char *imsi, char *resp, size_t resp_len) } +static int gsm_auth_req(char *imsi, char *resp, size_t resp_len) +{ + int count, ret; + char *pos, *rpos, *rend; + struct milenage_parameters *m; + + resp[0] = '\0'; + + pos = os_strchr(imsi, ' '); + if (!pos) + return -1; + *pos++ = '\0'; + + rend = resp + resp_len; + rpos = resp; + ret = os_snprintf(rpos, rend - rpos, "GSM-AUTH-RESP %s", imsi); + if (os_snprintf_error(rend - rpos, ret)) + return -1; + rpos += ret; + + m = get_milenage(imsi); + if (m) { + u8 _rand[16], sres[4], kc[8]; + for (count = 0; count < EAP_SIM_MAX_CHAL; count++) { + if (hexstr2bin(pos, _rand, 16) != 0) + return -1; + gsm_milenage(m->opc, m->ki, _rand, sres, kc); + *rpos++ = count == 0 ? ' ' : ':'; + rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8); + *rpos++ = ':'; + rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4); + pos += 16 * 2; + if (*pos != ':') + break; + pos++; + } + *rpos = '\0'; + return 0; + } + + printf("No GSM triplets found for %s\n", imsi); + ret = os_snprintf(rpos, rend - rpos, " FAILURE"); + if (os_snprintf_error(rend - rpos, ret)) + return -1; + rpos += ret; + + return 0; +} + + static void inc_sqn(u8 *sqn) { u64 val, seq, ind; @@ -745,6 +762,10 @@ static int aka_req_auth(char *imsi, char *resp, size_t resp_len) } milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand, autn, ik, ck, res, &res_len); + if (m->res_len >= EAP_AKA_RES_MIN_LEN && + m->res_len <= EAP_AKA_RES_MAX_LEN && + m->res_len < res_len) + res_len = m->res_len; } else { printf("Unknown IMSI: %s\n", imsi); #ifdef AKA_USE_FIXED_TEST_VALUES @@ -847,6 +868,9 @@ static int process_cmd(char *cmd, char *resp, size_t resp_len) if (os_strncmp(cmd, "SIM-REQ-AUTH ", 13) == 0) return sim_req_auth(cmd + 13, resp, resp_len); + if (os_strncmp(cmd, "GSM-AUTH-REQ ", 13) == 0) + return gsm_auth_req(cmd + 13, resp, resp_len); + if (os_strncmp(cmd, "AKA-REQ-AUTH ", 13) == 0) return aka_req_auth(cmd + 13, resp, resp_len); @@ -949,7 +973,7 @@ static void usage(void) { printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA " "database/authenticator\n" - "Copyright (c) 2005-2007, 2012-2013, Jouni Malinen \n" + "Copyright (c) 2005-2017, Jouni Malinen \n" "\n" "usage:\n" "hlr_auc_gw [-hu] [-s] [-g] "