From 98a95ac17f701d94d2fa62d91cfe42a5beef4f23 Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Fri, 28 Nov 2014 14:55:25 +0100 Subject: 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 --- openbsc/include/openbsc/gprs_sgsn.h | 15 +++- openbsc/src/gprs/gprs_subscriber.c | 91 +++++++++++++++++-------- openbsc/src/gprs/sgsn_auth.c | 79 ++++++++++++++++++--- openbsc/src/gprs/sgsn_vty.c | 72 +++++++++++++++++++- openbsc/tests/sgsn/Makefile.am | 3 +- openbsc/tests/sgsn/sgsn_test.c | 132 ++++++++++++++++++++++++++---------- openbsc/tests/sgsn/sgsn_test.ok | 1 + 7 files changed, 311 insertions(+), 82 deletions(-) (limited to 'openbsc') 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 #include #include - +#include #include 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) -- cgit v1.2.3