diff --git a/src/ctrl.c b/src/ctrl.c index 562ee756..c5435590 100644 --- a/src/ctrl.c +++ b/src/ctrl.c @@ -37,6 +37,9 @@ #define SEL_BY_MSISDN SEL_BY "msisdn-" #define SEL_BY_ID SEL_BY "id-" +extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo, + int *minlen, int *maxlen); + #define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf)) static bool startswith(const char *str, const char *start) @@ -473,6 +476,106 @@ static int set_subscr_msisdn(struct ctrl_cmd *cmd, void *data) return CTRL_CMD_REPLY; } +/* value format: */ +CTRL_CMD_DEFINE(subscr_aud2g, "aud2g"); +static int verify_subscr_aud2g(struct ctrl_cmd *cmd, const char *value, void *data) +{ + if (!value) + return 1; + if (strcasecmp(value, "none") != 0 && !strchr(value, ',')) + return 1; + return 0; +} +static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data) +{ + struct hlr_subscriber subscr; + struct hlr *hlr = data; + const char *by_selector = cmd->node; + struct osmo_sub_auth_data aud2g; + struct osmo_sub_auth_data aud3g_unused; + int rc; + + if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd)) + return CTRL_CMD_ERROR; + + rc = db_get_auth_data(hlr->dbc, subscr.imsi, &aud2g, &aud3g_unused, NULL); + switch (rc) { + case 0: + break; + case -ENOENT: + case -ENOKEY: + aud2g.algo = OSMO_AUTH_ALG_NONE; + break; + default: + cmd->reply = "Error retrieving data from database."; + return CTRL_CMD_ERROR; + } + + if (aud2g.algo == OSMO_AUTH_ALG_NONE) { + cmd->reply = "none"; + return CTRL_CMD_REPLY; + } + + cmd->reply = talloc_asprintf(cmd, "%s,%s", osmo_auth_alg_name(aud2g.algo), + hexdump_buf(aud2g.u.gsm.ki)); + return CTRL_CMD_REPLY; +} +static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data) +{ + struct hlr_subscriber subscr; + struct hlr *hlr = data; + const char *by_selector = cmd->node; + char *tmp = NULL, *tok, *saveptr; + int minlen = 0; + int maxlen = 0; + struct sub_auth_data_str aud2g = { + .type = OSMO_AUTH_TYPE_GSM + }; + + if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd)) + return CTRL_CMD_ERROR; + + tmp = talloc_strdup(cmd, cmd->value); + if (!tmp) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + + /* Parse alg_type: */ + tok = strtok_r(tmp, ",", &saveptr); + if (!tok) { + cmd->reply = "Invalid format"; + return CTRL_CMD_ERROR; + } + if (strcmp(tok, "none") == 0) { + aud2g.algo = OSMO_AUTH_ALG_NONE; + } else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen)) { + cmd->reply = "Unknown auth algorithm."; + return CTRL_CMD_ERROR; + } + + if (aud2g.algo != OSMO_AUTH_ALG_NONE) { + tok = strtok_r(NULL, "\0", &saveptr); + if (!tok) { + cmd->reply = "Invalid format."; + return CTRL_CMD_ERROR; + } + aud2g.u.gsm.ki = tok; + if (!osmo_is_hexstr(aud2g.u.gsm.ki, minlen * 2, maxlen * 2, true)) { + cmd->reply = "Invalid KI."; + return CTRL_CMD_ERROR; + } + } + + if (db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud2g)) { + cmd->reply = "Update aud2g failed."; + return CTRL_CMD_ERROR; + } + + cmd->reply = "OK"; + return CTRL_CMD_REPLY; +} + static int hlr_ctrl_node_lookup(void *data, vector vline, int *node_type, void **node_data, int *i) { @@ -511,6 +614,7 @@ static int hlr_ctrl_cmds_install() rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_ps_enabled); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_cs_enabled); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_msisdn); + rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud2g); return rc; } diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c index 3813393e..a9f461d2 100644 --- a/src/hlr_vty_subscr.c +++ b/src/hlr_vty_subscr.c @@ -476,8 +476,8 @@ static bool is_hexkey_valid(struct vty *vty, const char *label, #define MILENAGE_KEY_LEN 16 -static bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo, - int *minlen, int *maxlen) +bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo, + int *minlen, int *maxlen) { if (!strcasecmp(alg_str, "none")) { *algo = OSMO_AUTH_ALG_NONE; diff --git a/tests/test_subscriber.ctrl b/tests/test_subscriber.ctrl index 889f0a7e..dadad356 100644 --- a/tests/test_subscriber.ctrl +++ b/tests/test_subscriber.ctrl @@ -671,5 +671,20 @@ periodic_lu_timer 0 periodic_rau_tau_timer 0 lmsi 00000000 -SET 112 subscriber.delete 901991234567891 -SET_REPLY 112 subscriber.delete 124 +GET 112 subscriber.by-imsi-901991234567891.aud2g +GET_REPLY 112 subscriber.by-imsi-901991234567891.aud2g none + +SET 113 subscriber.by-imsi-901991234567891.aud2g xor,c01ffedc1cadaeac1d1f1edacac1ab0a +SET_REPLY 113 subscriber.by-imsi-901991234567891.aud2g OK + +GET 114 subscriber.by-imsi-901991234567891.aud2g +GET_REPLY 114 subscriber.by-imsi-901991234567891.aud2g XOR,c01ffedc1cadaeac1d1f1edacac1ab0a + +SET 115 subscriber.by-imsi-901991234567891.aud2g none +SET_REPLY 115 subscriber.by-imsi-901991234567891.aud2g OK + +GET 116 subscriber.by-imsi-901991234567891.aud2g +GET_REPLY 116 subscriber.by-imsi-901991234567891.aud2g none + +SET 117 subscriber.delete 901991234567891 +SET_REPLY 117 subscriber.delete 124 diff --git a/tests/test_subscriber_errors.ctrl b/tests/test_subscriber_errors.ctrl index 403e0fa0..ac9eec7e 100644 --- a/tests/test_subscriber_errors.ctrl +++ b/tests/test_subscriber_errors.ctrl @@ -123,3 +123,12 @@ ERROR 52 Subscriber doesn't exist. SET 53 subscriber.delete zzz ERROR 53 Invalid IMSI value. + +SET 54 subscriber.by-imsi-901990000000003.aud2g foobar +ERROR 54 Value failed verification. + +SET 55 subscriber.by-imsi-901990000000003.aud2g foobar,2134 +ERROR 55 Unknown auth algorithm. + +SET 56 subscriber.by-imsi-901990000000003.aud2g xor,2134 +ERROR 56 Invalid KI.