From a44b97059221f62056b3608abd7cfba3d9cf214c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 30 Jul 2018 17:53:28 +0200 Subject: [PATCH] migrate to oap_client in libosmogsm libosmogsm in libosmocore.git from Change-Id Ie36729996abd30b84d1c30a09f62ebc6a9794950 onwards contains oap_client.c, so we don't need our local copy here in this repo anymore. Change-Id: Ib6496c35d0ce6eb531e97129dc45a9f68e503b34 Requires: libosmocore.git Change-Id Ie36729996abd30b84d1c30a09f62ebc6a9794950 --- include/osmocom/msc/Makefile.am | 1 - include/osmocom/msc/gsup_client.h | 6 +- include/osmocom/msc/oap_client.h | 82 --------- src/libgsupclient/Makefile.am | 1 - src/libgsupclient/gsup_client.c | 11 +- src/libgsupclient/oap_client.c | 281 ------------------------------ tests/msc_vlr/msc_vlr_tests.c | 4 +- 7 files changed, 11 insertions(+), 375 deletions(-) delete mode 100644 include/osmocom/msc/oap_client.h delete mode 100644 src/libgsupclient/oap_client.c diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am index 5be51ea90..b1a4810df 100644 --- a/include/osmocom/msc/Makefile.am +++ b/include/osmocom/msc/Makefile.am @@ -21,7 +21,6 @@ noinst_HEADERS = \ mncc_int.h \ msc_ifaces.h \ msc_mgcp.h \ - oap_client.h \ openbscdefines.h \ a_reset.h \ osmo_msc.h \ diff --git a/include/osmocom/msc/gsup_client.h b/include/osmocom/msc/gsup_client.h index 59e650f63..2f6170b63 100644 --- a/include/osmocom/msc/gsup_client.h +++ b/include/osmocom/msc/gsup_client.h @@ -23,7 +23,7 @@ #include -#include +#include /* a loss of GSUP between MSC and HLR is considered quite serious, let's try to recover as quickly as * possible. Even one new connection attempt per second should be quite acceptable until the link is @@ -46,7 +46,7 @@ struct gsup_client { gsup_client_read_cb_t read_cb; void *data; - struct oap_client_state oap_state; + struct osmo_oap_client_state oap_state; struct osmo_timer_list ping_timer; struct osmo_timer_list connect_timer; @@ -59,7 +59,7 @@ struct gsup_client *gsup_client_create(void *talloc_ctx, const char *ip_addr, unsigned int tcp_port, gsup_client_read_cb_t read_cb, - struct oap_client_config *oapc_config); + struct osmo_oap_client_config *oapc_config); void gsup_client_destroy(struct gsup_client *gsupc); int gsup_client_send(struct gsup_client *gsupc, struct msgb *msg); diff --git a/include/osmocom/msc/oap_client.h b/include/osmocom/msc/oap_client.h deleted file mode 100644 index 80c86d5d6..000000000 --- a/include/osmocom/msc/oap_client.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Osmocom Authentication Protocol API */ - -/* (C) 2015 by Sysmocom s.f.m.c. GmbH - * All Rights Reserved - * - * Author: Neels Hofmeyr - * - * 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 . - * - */ - -#pragma once - -#include - -struct msgb; -struct osmo_oap_message; - -/* This is the config part for vty. It is essentially copied in - * oap_client_state, where values are copied over once the config is - * considered valid. */ -struct oap_client_config { - uint16_t client_id; - int secret_k_present; - uint8_t secret_k[16]; - int secret_opc_present; - uint8_t secret_opc[16]; -}; - -/* The runtime state of the OAP client. client_id and the secrets are in fact - * duplicated from oap_client_config, so that a separate validation of the - * config data is possible, and so that only a struct oap_client_state* is - * passed around. */ -struct oap_client_state { - enum { - OAP_UNINITIALIZED = 0, /* just allocated. */ - OAP_DISABLED, /* disabled by config. */ - OAP_INITIALIZED, /* enabled, config is valid. */ - OAP_REQUESTED_CHALLENGE, - OAP_SENT_CHALLENGE_RESULT, - OAP_REGISTERED - } state; - uint16_t client_id; - uint8_t secret_k[16]; - uint8_t secret_opc[16]; - int registration_failures; -}; - -/* From config, initialize state. Return 0 on success. */ -int oap_client_init(struct oap_client_config *config, - struct oap_client_state *state); - -/* Construct an OAP registration message and return in *msg_tx. Use - * state->client_id and update state->state. - * Return 0 on success, or a negative value on error. - * If an error is returned, *msg_tx is guaranteed to be NULL. */ -int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx); - -/* Decode and act on a received OAP message msg_rx. Update state->state. If a - * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP - * server (and freed) by the caller. The received msg_rx is not freed. - * Return 0 on success, or a negative value on error. - * If an error is returned, *msg_tx is guaranteed to be NULL. */ -int oap_client_handle(struct oap_client_state *state, - const struct msgb *msg_rx, struct msgb **msg_tx); - -/* Allocate a msgb and in it, return the encoded oap_client_msg. Return - * NULL on error. (Like oap_client_encode(), but also allocates a msgb.) - * About the name: the idea is do_something(oap_client_encoded(my_struct)) - */ -struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_client_msg); diff --git a/src/libgsupclient/Makefile.am b/src/libgsupclient/Makefile.am index a33fb38fa..6381687e4 100644 --- a/src/libgsupclient/Makefile.am +++ b/src/libgsupclient/Makefile.am @@ -19,7 +19,6 @@ noinst_LIBRARIES = \ libgsupclient_a_SOURCES = \ gsup_client.c \ - oap_client.c \ $(NULL) noinst_PROGRAMS = \ diff --git a/src/libgsupclient/gsup_client.c b/src/libgsupclient/gsup_client.c index 1f395eeb8..39dc181b4 100644 --- a/src/libgsupclient/gsup_client.c +++ b/src/libgsupclient/gsup_client.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -114,7 +115,7 @@ static void gsup_client_oap_register(struct gsup_client *gsupc) { struct msgb *msg_tx; int rc; - rc = oap_client_register(&gsupc->oap_state, &msg_tx); + rc = osmo_oap_client_register(&gsupc->oap_state, &msg_tx); if ((rc < 0) || (!msg_tx)) { LOGP(DLGSUP, LOGL_ERROR, "GSUP OAP set up, but cannot register.\n"); @@ -136,7 +137,7 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) if (up) { start_test_procedure(gsupc); - if (gsupc->oap_state.state == OAP_INITIALIZED) + if (gsupc->oap_state.state == OSMO_OAP_INITIALIZED) gsup_client_oap_register(gsupc); osmo_timer_del(&gsupc->connect_timer); @@ -154,7 +155,7 @@ static int gsup_client_oap_handle(struct gsup_client *gsupc, struct msgb *msg_rx struct msgb *msg_tx; /* If the oap_state is disabled, this will reject the messages. */ - rc = oap_client_handle(&gsupc->oap_state, msg_rx, &msg_tx); + rc = osmo_oap_client_handle(&gsupc->oap_state, msg_rx, &msg_tx); msgb_free(msg_rx); if (rc < 0) return rc; @@ -268,7 +269,7 @@ struct gsup_client *gsup_client_create(void *talloc_ctx, const char *ip_addr, unsigned int tcp_port, gsup_client_read_cb_t read_cb, - struct oap_client_config *oapc_config) + struct osmo_oap_client_config *oapc_config) { struct gsup_client *gsupc; int rc; @@ -283,7 +284,7 @@ struct gsup_client *gsup_client_create(void *talloc_ctx, OSMO_ASSERT(gsupc->unit_name); /* a NULL oapc_config will mark oap_state disabled. */ - rc = oap_client_init(oapc_config, &gsupc->oap_state); + rc = osmo_oap_client_init(oapc_config, &gsupc->oap_state); if (rc != 0) goto failed; diff --git a/src/libgsupclient/oap_client.c b/src/libgsupclient/oap_client.c deleted file mode 100644 index 137515a5a..000000000 --- a/src/libgsupclient/oap_client.c +++ /dev/null @@ -1,281 +0,0 @@ -/* Osmocom Authentication Protocol API */ - -/* (C) 2015 by Sysmocom s.f.m.c. GmbH - * All Rights Reserved - * - * Author: Neels Hofmeyr - * - * 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 -#include - -#include -#include - -int oap_client_init(struct oap_client_config *config, - struct oap_client_state *state) -{ - OSMO_ASSERT(state->state == OAP_UNINITIALIZED); - - if (!config) - goto disable; - - if (config->client_id == 0) - goto disable; - - if (config->secret_k_present == 0) { - LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n"); - goto disable; - } - - if (config->secret_opc_present == 0) { - LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n"); - goto disable; - } - - state->client_id = config->client_id; - memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k)); - memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc)); - state->state = OAP_INITIALIZED; - return 0; - -disable: - state->state = OAP_DISABLED; - return 0; -} - -/* From the given state and received RAND and AUTN octets, validate the - * server's authenticity and formulate the matching milenage reply octets in - * *tx_xres. The state is not modified. - * On success, and if tx_res is not NULL, exactly 8 octets will be written to - * *tx_res. If not NULL, tx_res must point at allocated memory of at least 8 - * octets. The caller will want to send XRES back to the server in a challenge - * response message and update the state. - * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail - * the authentication check; -3 for any other errors. */ -static int oap_evaluate_challenge(const struct oap_client_state *state, - const uint8_t *rx_random, - const uint8_t *rx_autn, - uint8_t *tx_xres) -{ - struct osmo_auth_vector vec; - - struct osmo_sub_auth_data auth = { - .type = OSMO_AUTH_TYPE_UMTS, - .algo = OSMO_AUTH_ALG_MILENAGE, - }; - - osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k) - == sizeof(state->secret_k), _secret_k_size_match); - osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc) - == sizeof(state->secret_opc), _secret_opc_size_match); - - switch (state->state) { - case OAP_UNINITIALIZED: - case OAP_DISABLED: - return -1; - default: - break; - } - - memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); - memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); - memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf)); - auth.u.umts.sqn = 41; /* TODO use incrementing sequence nr */ - - memset(&vec, 0, sizeof(vec)); - osmo_auth_gen_vec(&vec, &auth, rx_random); - - if (vec.res_len != 8) { - LOGP(DLOAP, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n", - vec.res_len); - return -3; - } - - if (osmo_constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) { - LOGP(DLOAP, LOGL_ERROR, "OAP: AUTN mismatch!\n"); - LOGP(DLOAP, LOGL_INFO, "OAP: AUTN from server: %s\n", - osmo_hexdump_nospc(rx_autn, sizeof(vec.autn))); - LOGP(DLOAP, LOGL_INFO, "OAP: AUTN expected: %s\n", - osmo_hexdump_nospc(vec.autn, sizeof(vec.autn))); - return -2; - } - - if (tx_xres != NULL) - memcpy(tx_xres, vec.res, 8); - return 0; -} - -struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_msg) -{ - struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); - OSMO_ASSERT(msg); - osmo_oap_encode(msg, oap_msg); - return msg; -} - -/* Create a new msgb containing an OAP registration message. - * On error, return NULL. */ -static struct msgb* oap_msg_register(uint16_t client_id) -{ - struct osmo_oap_message oap_msg = {0}; - - if (client_id < 1) { - LOGP(DLOAP, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id); - return NULL; - } - - oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; - oap_msg.client_id = client_id; - return oap_client_encoded(&oap_msg); -} - -int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx) -{ - *msg_tx = oap_msg_register(state->client_id); - if (!(*msg_tx)) - return -1; - - state->state = OAP_REQUESTED_CHALLENGE; - return 0; -} - -/* Create a new msgb containing an OAP challenge response message. - * xres must point at 8 octets to return as challenge response. - * On error, return NULL. */ -static struct msgb* oap_msg_challenge_response(uint8_t *xres) -{ - struct osmo_oap_message oap_reply = {0}; - - oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT; - memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres)); - oap_reply.xres_present = 1; - return oap_client_encoded(&oap_reply); -} - -static int handle_challenge(struct oap_client_state *state, - struct osmo_oap_message *oap_rx, - struct msgb **msg_tx) -{ - int rc; - uint8_t xres[8]; - - if (!(oap_rx->rand_present && oap_rx->autn_present)) { - LOGP(DLOAP, LOGL_ERROR, - "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n", - oap_rx->rand_present, oap_rx->autn_present); - rc = -2; - goto failure; - } - - rc = oap_evaluate_challenge(state, - oap_rx->rand, - oap_rx->autn, - xres); - if (rc < 0) - goto failure; - - *msg_tx = oap_msg_challenge_response(xres); - if ((*msg_tx) == NULL) { - rc = -1; - goto failure; - } - - state->state = OAP_SENT_CHALLENGE_RESULT; - return 0; - -failure: - OSMO_ASSERT(rc < 0); - state->state = OAP_INITIALIZED; - return rc; -} - -int oap_client_handle(struct oap_client_state *state, - const struct msgb *msg_rx, struct msgb **msg_tx) -{ - uint8_t *data = msgb_l2(msg_rx); - size_t data_len = msgb_l2len(msg_rx); - struct osmo_oap_message oap_msg = {0}; - int rc = 0; - - *msg_tx = NULL; - - OSMO_ASSERT(data); - - rc = osmo_oap_decode(&oap_msg, data, data_len); - if (rc < 0) { - LOGP(DLOAP, LOGL_ERROR, - "Decoding OAP message failed with error '%s' (%d)\n", - get_value_string(gsm48_gmm_cause_names, -rc), -rc); - return -10; - } - - switch (state->state) { - case OAP_UNINITIALIZED: - LOGP(DLOAP, LOGL_ERROR, - "Received OAP message %d, but the OAP client is" - " not initialized\n", oap_msg.message_type); - return -ENOTCONN; - case OAP_DISABLED: - LOGP(DLOAP, LOGL_ERROR, - "Received OAP message %d, but the OAP client is" - " disabled\n", oap_msg.message_type); - return -ENOTCONN; - default: - break; - } - - switch (oap_msg.message_type) { - case OAP_MSGT_CHALLENGE_REQUEST: - return handle_challenge(state, &oap_msg, msg_tx); - - case OAP_MSGT_REGISTER_RESULT: - /* successfully registered */ - state->state = OAP_REGISTERED; - break; - - case OAP_MSGT_REGISTER_ERROR: - LOGP(DLOAP, LOGL_ERROR, - "OAP registration failed\n"); - state->state = OAP_INITIALIZED; - if (state->registration_failures < 3) { - state->registration_failures++; - return oap_client_register(state, msg_tx); - } - return -11; - - case OAP_MSGT_REGISTER_REQUEST: - case OAP_MSGT_CHALLENGE_RESULT: - LOGP(DLOAP, LOGL_ERROR, - "Received invalid OAP message type for OAP client side: %d\n", - (int)oap_msg.message_type); - return -12; - - default: - LOGP(DLOAP, LOGL_ERROR, - "Unknown OAP message type: %d\n", - (int)oap_msg.message_type); - return -13; - } - - return 0; -} diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c index b38bfe0d7..14881096e 100644 --- a/tests/msc_vlr/msc_vlr_tests.c +++ b/tests/msc_vlr/msc_vlr_tests.c @@ -497,11 +497,11 @@ int mncc_recv(struct gsm_network *net, struct msgb *msg) struct gsup_client * __real_gsup_client_create(const char *ip_addr, unsigned int tcp_port, gsup_client_read_cb_t read_cb, - struct oap_client_config *oap_config); + struct osmo_oap_client_config *oap_config); struct gsup_client * __wrap_gsup_client_create(const char *ip_addr, unsigned int tcp_port, gsup_client_read_cb_t read_cb, - struct oap_client_config *oap_config) + struct osmo_oap_client_config *oap_config) { struct gsup_client *gsupc; gsupc = talloc_zero(msc_vlr_tests_ctx, struct gsup_client);