/* (C) 2012 by Harald Welte * * 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 . * */ #include #include #include #include #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; }