From 2e5e94c3283fa4f5160962f42e7cd5d4e39b7d1e Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Mon, 8 Dec 2014 15:26:47 +0100 Subject: sgsn: Support subscriber based authentication This commit mainly extends sgsn_auth.c to use and support the auth_state SGSN_AUTH_AUTHENTICATE. It will be activated when IMSI and IMEI are available, authentication is required (subscr->sgsn_data->authenticate is set), but the MM context is not marked as authenticated. If the state has been set to SGSN_AUTH_AUTHENTICATE and sgsn_auth_update() is called, the GMM layer will be informed by invoking gsm0408_gprs_authenticate(). Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gprs_sgsn.h | 4 +-- openbsc/src/gprs/sgsn_auth.c | 7 +++++ openbsc/src/gprs/sgsn_vty.c | 8 ++++-- openbsc/tests/sgsn/sgsn_test.c | 55 +++++++++++++++++++++++++++++++++++++ openbsc/tests/sgsn/sgsn_test.ok | 1 + 5 files changed, 70 insertions(+), 5 deletions(-) diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h index 1b6338998..d3cd8bb2f 100644 --- a/openbsc/include/openbsc/gprs_sgsn.h +++ b/openbsc/include/openbsc/gprs_sgsn.h @@ -272,8 +272,8 @@ struct imsi_acl_entry { }; struct sgsn_subscriber_data { - struct sgsn_mm_ctx *mm; - enum sgsn_auth_state auth_state; + struct sgsn_mm_ctx *mm; + int authenticate; }; struct sgsn_config; diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c index 1f11948f1..1219176d6 100644 --- a/openbsc/src/gprs/sgsn_auth.c +++ b/openbsc/src/gprs/sgsn_auth.c @@ -110,6 +110,10 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx) if (mmctx->subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING) return mmctx->auth_state; + if (mmctx->subscr->sgsn_data->authenticate && + !mmctx->is_authenticated) + return SGSN_AUTH_AUTHENTICATE; + if (mmctx->subscr->authorized) return SGSN_AUTH_ACCEPTED; @@ -180,6 +184,9 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx) mmctx->auth_state = auth_state; switch (auth_state) { + case SGSN_AUTH_AUTHENTICATE: + gsm0408_gprs_authenticate(mmctx); + break; case SGSN_AUTH_ACCEPTED: gsm0408_gprs_access_granted(mmctx); break; diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index a73b77155..4bb6a86a4 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -441,15 +441,15 @@ DEFUN(show_subscr_cache, "The IMSI\n" DEFUN(update_subscr_insert, update_subscr_insert_cmd, - UPDATE_SUBSCR_STR "insert authorized (0|1)", + UPDATE_SUBSCR_STR "insert (authorized|authenticate) (0|1)", UPDATE_SUBSCR_HELP "Insert data into the subscriber record\n" "Authorize the subscriber to attach\n" "New option value\n") { const char *imsi = argv[0]; - const char *option = "authorized"; - const char *value = argv[1]; + const char *option = argv[1]; + const char *value = argv[2]; struct gsm_subscriber *subscr; @@ -461,6 +461,8 @@ DEFUN(update_subscr_insert, update_subscr_insert_cmd, if (!strcmp(option, "authorized")) subscr->authorized = atoi(value); + else + subscr->sgsn_data->authenticate = atoi(value); subscr_put(subscr); diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index 26d81a7f1..f5f68206b 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -591,6 +591,60 @@ static void test_gmm_attach_subscr(void) subscr_request_update_cb = __real_gprs_subscr_request_update; } +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; + + OSMO_ASSERT(mmctx->subscr); + /* Prevent subscr from being deleted */ + subscr = subscr_get(mmctx->subscr); + + /* Start authentication procedure */ + gprs_subscr_update(subscr); + + /* This will cause a GPRS AUTH AND CIPHERING REQ (cksn broken) */ + OSMO_ASSERT(old_sgsn_tx_counter == sgsn_tx_counter - 1); + + /* Restore sgsn_tx_counter to keep test_gmm_attach happy */ + sgsn_tx_counter = old_sgsn_tx_counter; + + /* Fake an authentication */ + OSMO_ASSERT(subscr->sgsn_data->mm); + subscr->sgsn_data->mm->is_authenticated = 1; + gprs_subscr_update(subscr); + + subscr_put(subscr); + } + return rc; +}; + +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; + + sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE; + subscr_request_update_cb = my_subscr_request_update_fake_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: "); + test_gmm_attach(); + + subscr = gprs_subscr_get_by_imsi("123456789012345"); + OSMO_ASSERT(subscr != NULL); + gprs_subscr_delete(subscr); + + sgsn->cfg.auth_policy = saved_auth_policy; + subscr_request_update_cb = __real_gprs_subscr_request_update; +} + /* * Test the GMM Rejects */ @@ -1112,6 +1166,7 @@ int main(int argc, char **argv) test_gmm_status_no_mmctx(); test_gmm_attach_acl(); test_gmm_attach_subscr(); + test_gmm_attach_subscr_fake_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 4b061a5f9..7d739add4 100644 --- a/openbsc/tests/sgsn/sgsn_test.ok +++ b/openbsc/tests/sgsn/sgsn_test.ok @@ -7,6 +7,7 @@ Testing GMM detach accept (unexpected) 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 Testing GMM reject - Attach Request (invalid MI length) - Attach Request (invalid MI type) -- cgit v1.2.3