mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
hlr_auc_gw: Add support for processing command line operations
This allows hlr_auc_gw to be used to run a single operation without having to use it as a server. This can be useful, e.g., for generating GSM authentication triplets for external programs. For example: ./hlr_auc_gw -m hlr_auc_gw.milenage_db "SIM-REQ-AUTH 232010000000000" Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
2b5b875f34
commit
3e6547b5e8
@ -62,6 +62,7 @@ static char *milenage_file = NULL;
|
||||
static int update_milenage = 0;
|
||||
static int sqn_changes = 0;
|
||||
static int ind_len = 5;
|
||||
static int stdout_debug = 1;
|
||||
|
||||
/* GSM triplets */
|
||||
struct gsm_triplet {
|
||||
@ -218,6 +219,9 @@ static int db_update_milenage_sqn(struct milenage_parameters *m)
|
||||
{
|
||||
char cmd[128], val[13], *pos;
|
||||
|
||||
if (sqlite_db == NULL)
|
||||
return 0;
|
||||
|
||||
pos = val;
|
||||
pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
|
||||
*pos = '\0';
|
||||
@ -615,16 +619,15 @@ static struct milenage_parameters * get_milenage(const char *imsi)
|
||||
}
|
||||
|
||||
|
||||
static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
static int sim_req_auth(char *imsi, char *resp, size_t resp_len)
|
||||
{
|
||||
int count, max_chal, ret;
|
||||
char *pos;
|
||||
char reply[1000], *rpos, *rend;
|
||||
char *rpos, *rend;
|
||||
struct milenage_parameters *m;
|
||||
struct gsm_triplet *g;
|
||||
|
||||
reply[0] = '\0';
|
||||
resp[0] = '\0';
|
||||
|
||||
pos = strchr(imsi, ' ');
|
||||
if (pos) {
|
||||
@ -635,11 +638,11 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
} else
|
||||
max_chal = EAP_SIM_MAX_CHAL;
|
||||
|
||||
rend = &reply[sizeof(reply)];
|
||||
rpos = reply;
|
||||
rend = resp + resp_len;
|
||||
rpos = resp;
|
||||
ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
|
||||
if (ret < 0 || ret >= rend - rpos)
|
||||
return;
|
||||
return -1;
|
||||
rpos += ret;
|
||||
|
||||
m = get_milenage(imsi);
|
||||
@ -647,7 +650,7 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
u8 _rand[16], sres[4], kc[8];
|
||||
for (count = 0; count < max_chal; count++) {
|
||||
if (random_get_bytes(_rand, 16) < 0)
|
||||
return;
|
||||
return -1;
|
||||
gsm_milenage(m->opc, m->ki, _rand, sres, kc);
|
||||
*rpos++ = ' ';
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
|
||||
@ -657,7 +660,7 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
|
||||
}
|
||||
*rpos = '\0';
|
||||
goto send;
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
@ -681,15 +684,11 @@ static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
printf("No GSM triplets found for %s\n", imsi);
|
||||
ret = snprintf(rpos, rend - rpos, " FAILURE");
|
||||
if (ret < 0 || ret >= rend - rpos)
|
||||
return;
|
||||
return -1;
|
||||
rpos += ret;
|
||||
}
|
||||
|
||||
send:
|
||||
printf("Send: %s\n", reply);
|
||||
if (sendto(s, reply, rpos - reply, 0,
|
||||
(struct sockaddr *) from, fromlen) < 0)
|
||||
perror("send");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -715,11 +714,10 @@ static void inc_sqn(u8 *sqn)
|
||||
}
|
||||
|
||||
|
||||
static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
static int aka_req_auth(char *imsi, char *resp, size_t resp_len)
|
||||
{
|
||||
/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
|
||||
char reply[1000], *pos, *end;
|
||||
char *pos, *end;
|
||||
u8 _rand[EAP_AKA_RAND_LEN];
|
||||
u8 autn[EAP_AKA_AUTN_LEN];
|
||||
u8 ik[EAP_AKA_IK_LEN];
|
||||
@ -733,16 +731,18 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
m = get_milenage(imsi);
|
||||
if (m) {
|
||||
if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
|
||||
return;
|
||||
return -1;
|
||||
res_len = EAP_AKA_RES_MAX_LEN;
|
||||
inc_sqn(m->sqn);
|
||||
#ifdef CONFIG_SQLITE
|
||||
db_update_milenage_sqn(m);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
sqn_changes = 1;
|
||||
if (stdout_debug) {
|
||||
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]);
|
||||
}
|
||||
milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
|
||||
autn, ik, ck, res, &res_len);
|
||||
} else {
|
||||
@ -760,18 +760,18 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
#endif /* AKA_USE_FIXED_TEST_VALUES */
|
||||
}
|
||||
|
||||
pos = reply;
|
||||
end = &reply[sizeof(reply)];
|
||||
pos = resp;
|
||||
end = resp + resp_len;
|
||||
ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return;
|
||||
return -1;
|
||||
pos += ret;
|
||||
if (failed) {
|
||||
ret = snprintf(pos, end - pos, "FAILURE");
|
||||
if (ret < 0 || ret >= end - pos)
|
||||
return;
|
||||
return -1;
|
||||
pos += ret;
|
||||
goto done;
|
||||
return 0;
|
||||
}
|
||||
pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
|
||||
*pos++ = ' ';
|
||||
@ -783,65 +783,84 @@ static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
*pos++ = ' ';
|
||||
pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
|
||||
|
||||
done:
|
||||
printf("Send: %s\n", reply);
|
||||
|
||||
if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
|
||||
fromlen) < 0)
|
||||
perror("send");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
|
||||
char *imsi)
|
||||
static int aka_auts(char *imsi, char *resp, size_t resp_len)
|
||||
{
|
||||
char *auts, *__rand;
|
||||
u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
|
||||
struct milenage_parameters *m;
|
||||
|
||||
resp[0] = '\0';
|
||||
|
||||
/* AKA-AUTS <IMSI> <AUTS> <RAND> */
|
||||
|
||||
auts = strchr(imsi, ' ');
|
||||
if (auts == NULL)
|
||||
return;
|
||||
return -1;
|
||||
*auts++ = '\0';
|
||||
|
||||
__rand = strchr(auts, ' ');
|
||||
if (__rand == NULL)
|
||||
return;
|
||||
return -1;
|
||||
*__rand++ = '\0';
|
||||
|
||||
printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand);
|
||||
if (stdout_debug) {
|
||||
printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n",
|
||||
imsi, auts, __rand);
|
||||
}
|
||||
if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
|
||||
hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
|
||||
printf("Could not parse AUTS/RAND\n");
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
m = get_milenage(imsi);
|
||||
if (m == NULL) {
|
||||
printf("Unknown IMSI: %s\n", imsi);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
|
||||
printf("AKA-AUTS: Incorrect MAC-S\n");
|
||||
} else {
|
||||
memcpy(m->sqn, sqn, 6);
|
||||
if (stdout_debug) {
|
||||
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]);
|
||||
}
|
||||
#ifdef CONFIG_SQLITE
|
||||
db_update_milenage_sqn(m);
|
||||
#endif /* CONFIG_SQLITE */
|
||||
sqn_changes = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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, "AKA-REQ-AUTH ", 13) == 0)
|
||||
return aka_req_auth(cmd + 13, resp, resp_len);
|
||||
|
||||
if (os_strncmp(cmd, "AKA-AUTS ", 9) == 0)
|
||||
return aka_auts(cmd + 9, resp, resp_len);
|
||||
|
||||
printf("Unknown request: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int process(int s)
|
||||
{
|
||||
char buf[1000];
|
||||
char buf[1000], resp[1000];
|
||||
struct sockaddr_un from;
|
||||
socklen_t fromlen;
|
||||
ssize_t res;
|
||||
@ -863,14 +882,21 @@ static int process(int s)
|
||||
|
||||
printf("Received: %s\n", buf);
|
||||
|
||||
if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
|
||||
sim_req_auth(s, &from, fromlen, buf + 13);
|
||||
else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
|
||||
aka_req_auth(s, &from, fromlen, buf + 13);
|
||||
else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
|
||||
aka_auts(s, &from, fromlen, buf + 9);
|
||||
else
|
||||
printf("Unknown request: %s\n", buf);
|
||||
if (process_cmd(buf, resp, sizeof(resp)) < 0) {
|
||||
printf("Failed to process request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (resp[0] == '\0') {
|
||||
printf("No response\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Send: %s\n", resp);
|
||||
|
||||
if (sendto(s, resp, os_strlen(resp), 0, (struct sockaddr *) &from,
|
||||
fromlen) < 0)
|
||||
perror("send");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -898,7 +924,9 @@ static void cleanup(void)
|
||||
os_free(prev);
|
||||
}
|
||||
|
||||
if (serv_sock >= 0)
|
||||
close(serv_sock);
|
||||
if (socket_path)
|
||||
unlink(socket_path);
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
@ -926,7 +954,7 @@ static void usage(void)
|
||||
"usage:\n"
|
||||
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
|
||||
"[-m<milenage file>] \\\n"
|
||||
" [-D<DB file>] [-i<IND len in bits>]\n"
|
||||
" [-D<DB file>] [-i<IND len in bits>] [command]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -h = show this usage help\n"
|
||||
@ -936,7 +964,15 @@ static void usage(void)
|
||||
" -g<triplet file> = path for GSM authentication triplets\n"
|
||||
" -m<milenage file> = path for Milenage keys\n"
|
||||
" -D<DB file> = path to SQLite database\n"
|
||||
" -i<IND len in bits> = IND length for SQN (default: 5)\n",
|
||||
" -i<IND len in bits> = IND length for SQN (default: 5)\n"
|
||||
"\n"
|
||||
"If the optional command argument, like "
|
||||
"\"AKA-REQ-AUTH <IMSI>\" is used, a single\n"
|
||||
"command is processed with response sent to stdout. Otherwise, "
|
||||
"hlr_auc_gw opens\n"
|
||||
"a control interface and processes commands sent through it "
|
||||
"(e.g., by EAP server\n"
|
||||
"in hostapd).\n",
|
||||
default_socket_path);
|
||||
}
|
||||
|
||||
@ -946,6 +982,7 @@ int main(int argc, char *argv[])
|
||||
int c;
|
||||
char *gsm_triplet_file = NULL;
|
||||
char *sqlite_db_file = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
@ -1009,6 +1046,7 @@ int main(int argc, char *argv[])
|
||||
if (milenage_file && read_milenage(milenage_file) < 0)
|
||||
return -1;
|
||||
|
||||
if (optind == argc) {
|
||||
serv_sock = open_socket(socket_path);
|
||||
if (serv_sock < 0)
|
||||
return -1;
|
||||
@ -1021,6 +1059,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (;;)
|
||||
process(serv_sock);
|
||||
} else {
|
||||
char buf[1000];
|
||||
socket_path = NULL;
|
||||
stdout_debug = 0;
|
||||
if (process_cmd(argv[optind], buf, sizeof(buf)) < 0) {
|
||||
printf("FAIL\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
if (sqlite_db) {
|
||||
@ -1031,5 +1081,5 @@ int main(int argc, char *argv[])
|
||||
|
||||
os_program_deinit();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user