237 lines
5.0 KiB
C
237 lines
5.0 KiB
C
/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
|
|
*
|
|
* All Rights Reserved
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <osmocom/core/talloc.h>
|
|
#include <osmocom/core/utils.h>
|
|
#include "auc.h"
|
|
|
|
/*
|
|
# imsi,algo,ki,0,0,0,0
|
|
# imsi,algo,k,opc,amf,sqn,opc_is_op
|
|
2620301,1,000102030405060708090a0b0c0d0e0f,0,0,0,0
|
|
2620301,1,000102030405060708090a0b0c0d0e0f,0f0e0d0c0b0a09080706050403020100,0001,32,0
|
|
*/
|
|
|
|
static struct auc_rec *
|
|
auc_rec_from_csv(void *ctx, const char *line_orig, long offset_nextline)
|
|
{
|
|
char *line = talloc_strdup(ctx, line_orig);
|
|
char *tok;
|
|
struct auc_rec *rec;
|
|
|
|
if (!line)
|
|
return NULL;
|
|
|
|
rec = talloc_zero(ctx, struct auc_rec);
|
|
if (!rec) {
|
|
talloc_free(line);
|
|
return NULL;
|
|
}
|
|
|
|
/* IMSI */
|
|
tok = strtok(line, ",");
|
|
if (!tok)
|
|
goto ret_free;
|
|
strncpy(rec->imsi, tok, OSMO_MIN(strlen(tok), sizeof(rec->imsi)));
|
|
rec->imsi[sizeof(rec->imsi)-1] = '\0';
|
|
|
|
/* ALGO */
|
|
tok = strtok(NULL, ",");
|
|
if (!tok)
|
|
goto ret_free;
|
|
rec->auth.algo = atoi(tok);
|
|
if (rec->auth.algo > _OSMO_AUTH_ALG_NUM)
|
|
goto ret_free;
|
|
|
|
/* K / Ki */
|
|
tok = strtok(NULL, ",");
|
|
if (!tok)
|
|
goto ret_free;
|
|
|
|
switch (rec->auth.algo) {
|
|
case OSMO_AUTH_ALG_NONE:
|
|
|
|
break;
|
|
case OSMO_AUTH_ALG_COMP128v1:
|
|
case OSMO_AUTH_ALG_COMP128v2:
|
|
case OSMO_AUTH_ALG_COMP128v3:
|
|
osmo_hexparse(tok, rec->auth.u.gsm.ki,
|
|
sizeof(rec->auth.u.gsm.ki));
|
|
break;
|
|
case OSMO_AUTH_ALG_XOR:
|
|
case OSMO_AUTH_ALG_MILENAGE:
|
|
osmo_hexparse(tok, rec->auth.u.umts.k,
|
|
sizeof(rec->auth.u.umts.k));
|
|
/* OPC */
|
|
tok = strtok(NULL, ",");
|
|
if (!tok)
|
|
goto ret_free;
|
|
osmo_hexparse(tok, rec->auth.u.umts.opc,
|
|
sizeof(rec->auth.u.umts.opc));
|
|
/* AMF */
|
|
tok = strtok(NULL, ",");
|
|
if (!tok)
|
|
goto ret_free;
|
|
osmo_hexparse(tok, rec->auth.u.umts.amf,
|
|
sizeof(rec->auth.u.umts.amf));
|
|
/* SQN */
|
|
tok = strtok(NULL, ",");
|
|
if (!tok)
|
|
goto ret_free;
|
|
rec->auth.u.umts.sqn = strtoull(tok, NULL, 10);
|
|
if (strlen(tok) != 8)
|
|
printf("SQN must be 8 digits wide in order to support updates\n");
|
|
else {
|
|
/* save file offfset for SQN so we can update it */
|
|
rec->offset_sqn = offset_nextline - (strlen(line_orig) - (tok - line));
|
|
}
|
|
|
|
/* IS_OP */
|
|
tok = strtok(NULL, ",");
|
|
if (!tok)
|
|
goto ret_free;
|
|
if (tok[0] == '1')
|
|
rec->auth.u.umts.opc_is_op = 1;
|
|
break;
|
|
}
|
|
|
|
talloc_free(line);
|
|
|
|
return rec;
|
|
|
|
ret_free:
|
|
talloc_free(rec);
|
|
talloc_free(line);
|
|
return NULL;
|
|
}
|
|
|
|
static char *auc_rec_to_csv(void *ctx, const struct auc_rec *rec)
|
|
{
|
|
char *line = talloc_zero_size(ctx, 256);
|
|
char *cur = line;
|
|
int i;
|
|
|
|
if (!line)
|
|
return NULL;
|
|
|
|
i = sprintf("%s,%u,", rec->imsi, rec->auth.algo);
|
|
if (i < 0)
|
|
goto ret_free;
|
|
cur += i;
|
|
|
|
switch (rec->auth.algo) {
|
|
case OSMO_AUTH_ALG_NONE:
|
|
break;
|
|
case OSMO_AUTH_ALG_COMP128v1:
|
|
case OSMO_AUTH_ALG_COMP128v2:
|
|
case OSMO_AUTH_ALG_COMP128v3:
|
|
i = sprintf(cur, "%s,0,0,0,0",
|
|
osmo_hexdump_nospc(rec->auth.u.gsm.ki,
|
|
sizeof(rec->auth.u.gsm.ki)));
|
|
if (i < 0)
|
|
goto ret_free;
|
|
cur += i;
|
|
break;
|
|
case OSMO_AUTH_ALG_XOR:
|
|
case OSMO_AUTH_ALG_MILENAGE:
|
|
i = sprintf(cur, "%s,",
|
|
osmo_hexdump_nospc(rec->auth.u.umts.k,
|
|
sizeof(rec->auth.u.umts.k)));
|
|
if (i < 0)
|
|
goto ret_free;
|
|
cur += i;
|
|
|
|
i = sprintf(cur, "%s,",
|
|
osmo_hexdump_nospc(rec->auth.u.umts.opc,
|
|
sizeof(rec->auth.u.umts.opc)));
|
|
if (i < 0)
|
|
goto ret_free;
|
|
cur += i;
|
|
|
|
i = sprintf(cur, "%s,",
|
|
osmo_hexdump_nospc(rec->auth.u.umts.amf,
|
|
sizeof(rec->auth.u.umts.amf)));
|
|
if (i < 0)
|
|
goto ret_free;
|
|
cur += i;
|
|
|
|
i = sprintf(cur, "%llu,%u", rec->auth.u.umts.sqn,
|
|
rec->auth.u.umts.opc_is_op);
|
|
if (i < 0)
|
|
goto ret_free;
|
|
cur += i;
|
|
break;
|
|
}
|
|
|
|
return line;
|
|
|
|
ret_free:
|
|
talloc_free(line);
|
|
return NULL;
|
|
}
|
|
|
|
int auc_storage_read(void *ctx, const char *fname)
|
|
{
|
|
FILE *file = fopen(fname, "r");
|
|
char *line = talloc_zero_size(ctx, 256);
|
|
int rc, num = 0;
|
|
|
|
while ((line = fgets(line, 256, file))) {
|
|
struct auc_rec *rec;
|
|
long offset_nextline;
|
|
|
|
if (line[0] == '#')
|
|
continue;
|
|
|
|
offset_nextline = ftell(file);
|
|
|
|
rec = auc_rec_from_csv(ctx, line, offset_nextline);
|
|
if (!rec)
|
|
continue;
|
|
|
|
rc = auc_add_rec(rec);
|
|
if (rc == 0)
|
|
num++;
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
static int auc_rec_dump(void *priv, void *ctx,
|
|
const struct auc_rec *rec)
|
|
{
|
|
FILE *file = priv;
|
|
char *line;
|
|
int rc;
|
|
|
|
line = auc_rec_to_csv(ctx, rec);
|
|
if (!line)
|
|
return -EIO;
|
|
|
|
rc = fputs(line, file);
|
|
|
|
talloc_free(line);
|
|
|
|
return rc;
|
|
}
|