aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-11-28 14:55:25 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-12-24 16:50:30 +0100
commit98a95ac17f701d94d2fa62d91cfe42a5beef4f23 (patch)
treea41eba64f19692721521dc927b258387d9151828
parent7921ab1593f45f12588e074ad1280472416ae930 (diff)
sgsn: Add a subscriber based authentication phase
This implements the MAP way of subscriber validation when the MS tries to perform an Attach Request: 1. perform authentication (optionally invoke the sendAuthInfo procedure), starts the Auth & Ciph procedure 2. perform update location 3. insert subscriber data 4. finish the update location 5. Attach Accept / Attach Reject The authentication triplets are used and eventually updated if all of them have been used. This is currently accessible via the VTY interface by the following commands: - update-subscriber imsi IMSI update-auth-info - update-subscriber imsi IMSI update-location-result (ok|ERR-CAUSE) Sponsored-by: On-Waves ehf
-rw-r--r--openbsc/include/openbsc/gprs_sgsn.h15
-rw-r--r--openbsc/src/gprs/gprs_subscriber.c91
-rw-r--r--openbsc/src/gprs/sgsn_auth.c79
-rw-r--r--openbsc/src/gprs/sgsn_vty.c72
-rw-r--r--openbsc/tests/sgsn/Makefile.am3
-rw-r--r--openbsc/tests/sgsn/sgsn_test.c132
-rw-r--r--openbsc/tests/sgsn/sgsn_test.ok1
7 files changed, 311 insertions, 82 deletions
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 411462b07..61b84d873 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -296,16 +296,25 @@ struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
/*
* GPRS subscriber data
*/
-#define GPRS_SUBSCRIBER_UPDATE_PENDING (1 << 16)
-#define GPRS_SUBSCRIBER_CANCELLED (1 << 17)
+#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
+#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
+#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
+
+#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
+ GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
+ GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
+)
void gprs_subscr_init(struct sgsn_instance *sgi);
-int gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx);
+int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
+int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
void gprs_subscr_delete(struct gsm_subscriber *subscr);
struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi);
+struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx( struct sgsn_mm_ctx *mmctx);
struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi);
void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr);
void gprs_subscr_update(struct gsm_subscriber *subscr);
+void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr);
/* Called on subscriber data updates */
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c
index 16753315c..1f210298f 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -92,9 +92,18 @@ void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr)
gprs_subscr_delete(subscr);
}
-int gprs_subscr_query(struct gsm_subscriber *subscr)
+int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
{
- /* TODO: Implement remote query to MSC, ... */
+ /* TODO: Implement remote query to HLR, ... */
+
+ LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
+ "subscriber auth info is not available (remote query NYI)\n");
+ return -ENOTSUP;
+}
+
+int gprs_subscr_location_update(struct gsm_subscriber *subscr)
+{
+ /* TODO: Implement remote query to HLR, ... */
LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
"subscriber data is not available (remote query NYI)\n");
@@ -105,56 +114,80 @@ void gprs_subscr_update(struct gsm_subscriber *subscr)
{
LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
- subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_PENDING;
+ subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
+ subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
+
+ sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
+}
+
+void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
+{
+ LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
+ "Updating subscriber authentication info\n");
+
+ subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
}
-int gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx)
+struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
{
struct gsm_subscriber *subscr = NULL;
- int need_update = 0;
- int rc;
- LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
+ if (mmctx->subscr)
+ return subscr_get(mmctx->subscr);
- if (mmctx->subscr) {
- subscr = subscr_get(mmctx->subscr);
- } else if (mmctx->imsi[0]) {
+ if (mmctx->imsi[0])
subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
- need_update = 1;
- }
if (!subscr) {
subscr = gprs_subscr_get_or_create(mmctx->imsi);
subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
- need_update = 1;
}
if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
- need_update = 1;
}
- if (subscr->lac != mmctx->ra.lac) {
+ if (subscr->lac != mmctx->ra.lac)
subscr->lac = mmctx->ra.lac;
- need_update = 1;
- }
- if (need_update) {
- subscr->flags |= GPRS_SUBSCRIBER_UPDATE_PENDING;
- if (!mmctx->subscr) {
- subscr->sgsn_data->mm = mmctx;
- mmctx->subscr = subscr_get(subscr);
- }
+ subscr->sgsn_data->mm = mmctx;
+ mmctx->subscr = subscr_get(subscr);
- rc = gprs_subscr_query(subscr);
- subscr_put(subscr);
- return rc;
- }
- gprs_subscr_update(subscr);
+ return subscr;
+}
+
+int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
+{
+ struct gsm_subscriber *subscr = NULL;
+ int rc;
+
+ LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
+
+ subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
+
+ subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
+
+ rc = gprs_subscr_location_update(subscr);
+ subscr_put(subscr);
+ return rc;
+}
+
+int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
+{
+ struct gsm_subscriber *subscr = NULL;
+ int rc;
+
+ LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
+
+ subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
+
+ subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
+
+ rc = gprs_subscr_query_auth_info(subscr);
subscr_put(subscr);
- return 0;
+ return rc;
}
diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c
index b065c061a..3755a51d4 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -23,7 +23,7 @@
#include <openbsc/gprs_sgsn.h>
#include <openbsc/gprs_gmm.h>
#include <openbsc/gsm_subscriber.h>
-
+#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/debug.h>
const struct value_string auth_state_names[] = {
@@ -107,11 +107,12 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx)
if (!mmctx->subscr)
return mmctx->auth_state;
- if (mmctx->subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING)
+ if (mmctx->subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING_MASK)
return mmctx->auth_state;
if (mmctx->subscr->sgsn_data->authenticate &&
- !mmctx->is_authenticated)
+ (!mmctx->is_authenticated ||
+ mmctx->subscr->sgsn_data->auth_triplets_updated))
return SGSN_AUTH_AUTHENTICATE;
if (mmctx->subscr->authorized)
@@ -141,20 +142,60 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx)
return SGSN_AUTH_REJECTED;
}
+/*
+ * This function is directly called by e.g. the GMM layer. It returns either
+ * after calling sgsn_auth_update directly or after triggering an asynchronous
+ * procedure which will call sgsn_auth_update later on.
+ */
int sgsn_auth_request(struct sgsn_mm_ctx *mmctx)
{
+ struct gsm_subscriber *subscr;
+ struct gsm_auth_tuple *at;
+ int need_update_location;
+ int rc;
+
LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting authorization\n");
- if (sgsn->cfg.auth_policy == SGSN_AUTH_POLICY_REMOTE && !mmctx->subscr) {
- if (gprs_subscr_request_update(mmctx) >= 0) {
+ if (sgsn->cfg.auth_policy != SGSN_AUTH_POLICY_REMOTE) {
+ sgsn_auth_update(mmctx);
+ return 0;
+ }
+
+ need_update_location =
+ mmctx->subscr == NULL ||
+ mmctx->pending_req == GSM48_MT_GMM_ATTACH_REQ;
+
+ /* This has the side effect of registering the subscr with the mmctx */
+ subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
+ subscr_put(subscr);
+
+ OSMO_ASSERT(mmctx->subscr != NULL);
+
+ if (mmctx->subscr->sgsn_data->authenticate && !mmctx->is_authenticated) {
+ /* Find next tuple */
+ at = sgsn_auth_get_tuple(mmctx, mmctx->auth_triplet.key_seq);
+
+ if (!at) {
+ /* No valid tuple found, request fresh ones */
+ mmctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
LOGMMCTXP(LOGL_INFO, mmctx,
- "Missing information, requesting subscriber data\n");
- return 0;
+ "Requesting authentication tuples\n");
+ rc = gprs_subscr_request_auth_info(mmctx);
+ if (rc >= 0)
+ return 0;
+
+ return rc;
}
+
+ mmctx->auth_triplet = *at;
+ } else if (need_update_location) {
+ LOGMMCTXP(LOGL_INFO, mmctx,
+ "Missing information, requesting subscriber data\n");
+ if (gprs_subscr_request_update_location(mmctx) >= 0)
+ return 0;
}
sgsn_auth_update(mmctx);
-
return 0;
}
@@ -162,6 +203,7 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
{
enum sgsn_auth_state auth_state;
struct gsm_subscriber *subscr = mmctx->subscr;
+ struct gsm_auth_tuple *at;
auth_state = sgsn_auth_state(mmctx);
@@ -170,13 +212,27 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
get_value_string(sgsn_auth_state_names, auth_state));
if (auth_state == SGSN_AUTH_UNKNOWN && subscr &&
- !(subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING)) {
- /* Reject requests if gprs_subscr_request_update fails */
+ !(subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING_MASK)) {
+ /* Reject requests if gprs_subscr_request_update_location fails */
LOGMMCTXP(LOGL_ERROR, mmctx,
"Missing information, authorization not possible\n");
auth_state = SGSN_AUTH_REJECTED;
}
+ if (auth_state == SGSN_AUTH_AUTHENTICATE &&
+ mmctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
+ /* The current tuple is not valid, but we are possibly called
+ * because new auth tuples have been received */
+ at = sgsn_auth_get_tuple(mmctx, mmctx->auth_triplet.key_seq);
+ if (!at) {
+ LOGMMCTXP(LOGL_ERROR, mmctx,
+ "Missing auth tuples, authorization not possible\n");
+ auth_state = SGSN_AUTH_REJECTED;
+ } else {
+ mmctx->auth_triplet = *at;
+ }
+ }
+
if (mmctx->auth_state == auth_state)
return;
@@ -188,6 +244,9 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
switch (auth_state) {
case SGSN_AUTH_AUTHENTICATE:
+ if (subscr)
+ subscr->sgsn_data->auth_triplets_updated = 0;
+
gsm0408_gprs_authenticate(mmctx);
break;
case SGSN_AUTH_ACCEPTED:
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index 99c59853b..9b925a8cb 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -428,13 +428,15 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr,
}
if (subscr->flags)
- vty_out(vty, " Flags: %s%s%s%s",
+ vty_out(vty, " Flags: %s%s%s%s%s",
subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT ?
"FIRST_CONTACT " : "",
subscr->flags & GPRS_SUBSCRIBER_CANCELLED ?
"CANCELLED " : "",
- subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING ?
- "UPDATE_PENDING " : "",
+ subscr->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
+ "UPDATE_LOCATION_PENDING " : "",
+ subscr->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
+ "AUTH_INFO_PENDING " : "",
VTY_NEWLINE);
vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
@@ -587,6 +589,68 @@ DEFUN(update_subscr_commit, update_subscr_commit_cmd,
return CMD_SUCCESS;
}
+#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
+ "unknown-subscriber|roaming-not-allowed"
+
+#define UL_ERR_HELP \
+ "Force error code SystemFailure\n" \
+ "Force error code DataMissing\n" \
+ "Force error code UnexpectedDataValue\n" \
+ "Force error code UnknownSubscriber\n" \
+ "Force error code RoamingNotAllowed\n"
+
+DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
+ UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
+ UPDATE_SUBSCR_HELP
+ "Complete the update location procedure\n"
+ "The update location request succeeded\n"
+ UL_ERR_HELP)
+{
+ const char *imsi = argv[0];
+ const char *ret_code_str = argv[1];
+
+ struct gsm_subscriber *subscr;
+
+ subscr = gprs_subscr_get_by_imsi(imsi);
+ if (!subscr) {
+ vty_out(vty, "%% unable to get subscriber record for %s\n", imsi);
+ return CMD_WARNING;
+ }
+ if (strcmp(ret_code_str, "ok") == 0)
+ subscr->authorized = 1;
+ else
+ subscr->authorized = 0;
+
+ gprs_subscr_update(subscr);
+
+ subscr_put(subscr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
+ UPDATE_SUBSCR_STR "update-auth-info",
+ UPDATE_SUBSCR_HELP
+ "Complete the send authentication info procedure\n")
+{
+ const char *imsi = argv[0];
+
+ struct gsm_subscriber *subscr;
+
+ subscr = gprs_subscr_get_by_imsi(imsi);
+ if (!subscr) {
+ vty_out(vty, "%% unable to get subscriber record for %s\n", imsi);
+ return CMD_WARNING;
+ }
+
+ gprs_subscr_update_auth_info(subscr);
+
+ subscr_put(subscr);
+
+ return CMD_SUCCESS;
+}
+
+
int sgsn_vty_init(void)
{
install_element_ve(&show_sgsn_cmd);
@@ -600,6 +664,8 @@ int sgsn_vty_init(void)
install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
install_element(ENABLE_NODE, &update_subscr_commit_cmd);
+ install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
+ install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
install_element(CONFIG_NODE, &cfg_sgsn_cmd);
install_node(&sgsn_node, config_write_sgsn);
diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am
index 970311d0c..50c37d627 100644
--- a/openbsc/tests/sgsn/Makefile.am
+++ b/openbsc/tests/sgsn/Makefile.am
@@ -8,7 +8,8 @@ noinst_PROGRAMS = sgsn_test
sgsn_test_SOURCES = sgsn_test.c
sgsn_test_LDFLAGS = \
-Wl,--wrap=sgsn_update_subscriber_data \
- -Wl,--wrap=gprs_subscr_request_update
+ -Wl,--wrap=gprs_subscr_request_update_location \
+ -Wl,--wrap=gprs_subscr_request_auth_info
sgsn_test_LDADD = \
$(top_builddir)/src/gprs/gprs_llc_parse.o \
diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c
index b4f6fdb74..c7eec7bde 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -67,13 +67,22 @@ void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
(*update_subscriber_data_cb)(mmctx, subscr);
}
-/* override, requires '-Wl,--wrap=gprs_subscr_request_update' */
-int __real_gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx);
-int (*subscr_request_update_cb)(struct sgsn_mm_ctx *mmctx) =
- &__real_gprs_subscr_request_update;
+/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
+int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
+int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
+ &__real_gprs_subscr_request_update_location;
-int __wrap_gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
- return (*subscr_request_update_cb)(mmctx);
+int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
+ return (*subscr_request_update_location_cb)(mmctx);
+};
+
+/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
+int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
+int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
+ &__real_gprs_subscr_request_auth_info;
+
+int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
+ return (*subscr_request_auth_info_cb)(mmctx);
};
static int count(struct llist_head *head)
@@ -525,6 +534,12 @@ static void test_gmm_attach(void)
0x54
};
+ /* DTAP - Authentication and Ciphering Resp */
+ static const unsigned char auth_ciph_resp[] = {
+ 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
+ 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
+ };
+
/* DTAP - Attach Complete */
static const unsigned char attach_compl[] = {
0x08, 0x03
@@ -584,6 +599,19 @@ static void test_gmm_attach(void)
OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
+ if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE) {
+ /* we expect an auth & ciph request */
+ OSMO_ASSERT(sgsn_tx_counter == 1);
+
+ /* inject the auth & ciph response */
+ send_0408_message(ctx->llme, foreign_tlli,
+ auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
+
+ /* check that the MM context has not been removed due to a
+ * failed authorization */
+ OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
+ }
+
/* we expect an attach accept/reject */
OSMO_ASSERT(sgsn_tx_counter == 1);
@@ -622,9 +650,9 @@ static void test_gmm_attach_acl(void)
sgsn->cfg.auth_policy = saved_auth_policy;
}
-int my_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
+int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
int rc;
- rc = __real_gprs_subscr_request_update(mmctx);
+ rc = __real_gprs_subscr_request_update_location(mmctx);
if (rc == -ENOTSUP) {
OSMO_ASSERT(mmctx->subscr);
gprs_subscr_update(mmctx->subscr);
@@ -632,13 +660,19 @@ int my_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
return rc;
};
+int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
+ gprs_subscr_update(mmctx->subscr);
+ return 0;
+};
+
static void test_gmm_attach_subscr(void)
{
const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
struct gsm_subscriber *subscr;
sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
- subscr_request_update_cb = my_subscr_request_update;
+ subscr_request_update_location_cb = my_subscr_request_update_location;
+ subscr_request_auth_info_cb = my_subscr_request_auth_info;
subscr = gprs_subscr_get_or_create("123456789012345");
subscr->authorized = 1;
@@ -652,53 +686,77 @@ static void test_gmm_attach_subscr(void)
gprs_subscr_delete(subscr);
sgsn->cfg.auth_policy = saved_auth_policy;
- subscr_request_update_cb = __real_gprs_subscr_request_update;
+ subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
+ subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
}
-int my_subscr_request_update_fake_auth(struct sgsn_mm_ctx *mmctx) {
- int rc;
- rc = __real_gprs_subscr_request_update(mmctx);
- if (rc == -ENOTSUP) {
- struct gsm_subscriber *subscr;
- int old_sgsn_tx_counter = sgsn_tx_counter;
+int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
+{
+ /* Fake an authentication */
+ OSMO_ASSERT(mmctx->subscr);
+ mmctx->is_authenticated = 1;
+ gprs_subscr_update_auth_info(mmctx->subscr);
- OSMO_ASSERT(mmctx->subscr);
- /* Prevent subscr from being deleted */
- subscr = subscr_get(mmctx->subscr);
+ return 0;
+};
+
+static void test_gmm_attach_subscr_fake_auth(void)
+{
+ const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
+ struct gsm_subscriber *subscr;
- /* Start authentication procedure */
- gprs_subscr_update(subscr);
+ sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
+ subscr_request_update_location_cb = my_subscr_request_update_location;
+ subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
- /* This will cause a GPRS AUTH AND CIPHERING REQ (cksn broken) */
- OSMO_ASSERT(old_sgsn_tx_counter == sgsn_tx_counter - 1);
+ subscr = gprs_subscr_get_or_create("123456789012345");
+ subscr->authorized = 1;
+ subscr->sgsn_data->authenticate = 1;
+ subscr_put(subscr);
- /* Restore sgsn_tx_counter to keep test_gmm_attach happy */
- sgsn_tx_counter = old_sgsn_tx_counter;
+ printf("Auth policy 'remote', auth faked: ");
+ test_gmm_attach();
- /* Fake an authentication */
- OSMO_ASSERT(subscr->sgsn_data->mm);
- subscr->sgsn_data->mm->is_authenticated = 1;
- gprs_subscr_update(subscr);
+ subscr = gprs_subscr_get_by_imsi("123456789012345");
+ OSMO_ASSERT(subscr != NULL);
+ gprs_subscr_delete(subscr);
- subscr_put(subscr);
- }
- return rc;
+ sgsn->cfg.auth_policy = saved_auth_policy;
+ subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
+ subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
+}
+
+int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
+{
+ struct gsm_auth_tuple at = {
+ .sres = {0x51, 0xe5, 0x51, 0xe5},
+ .key_seq = 0
+ };
+
+ /* Fake an authentication */
+ OSMO_ASSERT(mmctx->subscr);
+ mmctx->subscr->sgsn_data->auth_triplets[0] = at;
+
+ gprs_subscr_update_auth_info(mmctx->subscr);
+
+ return 0;
};
-static void test_gmm_attach_subscr_fake_auth(void)
+static void test_gmm_attach_subscr_real_auth(void)
{
const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
struct gsm_subscriber *subscr;
sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
- subscr_request_update_cb = my_subscr_request_update_fake_auth;
+ subscr_request_update_location_cb = my_subscr_request_update_location;
+ subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
subscr = gprs_subscr_get_or_create("123456789012345");
subscr->authorized = 1;
subscr->sgsn_data->authenticate = 1;
subscr_put(subscr);
- printf("Auth policy 'remote', auth faked: ");
+ printf("Auth policy 'remote', triplet based auth: ");
test_gmm_attach();
subscr = gprs_subscr_get_by_imsi("123456789012345");
@@ -706,7 +764,8 @@ static void test_gmm_attach_subscr_fake_auth(void)
gprs_subscr_delete(subscr);
sgsn->cfg.auth_policy = saved_auth_policy;
- subscr_request_update_cb = __real_gprs_subscr_request_update;
+ subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
+ subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
}
/*
@@ -1232,6 +1291,7 @@ int main(int argc, char **argv)
test_gmm_attach_acl();
test_gmm_attach_subscr();
test_gmm_attach_subscr_fake_auth();
+ test_gmm_attach_subscr_real_auth();
test_gmm_reject();
test_gmm_cancel();
test_gmm_ptmsi_allocation();
diff --git a/openbsc/tests/sgsn/sgsn_test.ok b/openbsc/tests/sgsn/sgsn_test.ok
index eff47c423..e54991cb5 100644
--- a/openbsc/tests/sgsn/sgsn_test.ok
+++ b/openbsc/tests/sgsn/sgsn_test.ok
@@ -9,6 +9,7 @@ Testing GMM Status (no MMCTX)
Auth policy 'closed': Testing GMM attach
Auth policy 'remote': Testing GMM attach
Auth policy 'remote', auth faked: Testing GMM attach
+Auth policy 'remote', triplet based auth: Testing GMM attach
Testing GMM reject
- Attach Request (invalid MI length)
- Attach Request (invalid MI type)