aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-11-12 10:18:09 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-12-09 09:27:20 +0100
commitbe2c8d9358084092281e7d02dc7ae0b7e4c0b4f8 (patch)
tree447342f2c1aac8287c5538c22191e1cd06baf9b3 /openbsc
parent33b6dadc884ec1060e401ba097523086ac34b552 (diff)
sgsn: Integrate subscriber handling into the SGSN
This commit adds a new authorization policy 'remote' and uses the subscriber cache for authorization when this policy is being used. Note that there is no remote backend implemented yet. After the IMSI/IMEI have been acquired, a request would be sent to the remote peer. The attach/auth-ciph procedure continues when authorization info has been received from the peer. This means, that gprs_subscr_update() must be called then to tell the GMM layer that it can proceed. A later commit will add VTY commands to do this manually. Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/sgsn.h3
-rw-r--r--openbsc/src/gprs/gprs_sgsn.c27
-rw-r--r--openbsc/src/gprs/sgsn_auth.c29
-rw-r--r--openbsc/src/gprs/sgsn_vty.c8
-rw-r--r--openbsc/tests/sgsn/Makefile.am3
-rw-r--r--openbsc/tests/sgsn/sgsn_test.c57
-rw-r--r--openbsc/tests/sgsn/sgsn_test.ok3
-rw-r--r--openbsc/tests/vty_test_runner.py3
8 files changed, 120 insertions, 13 deletions
diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h
index 33bc72f9d..6b83337d0 100644
--- a/openbsc/include/openbsc/sgsn.h
+++ b/openbsc/include/openbsc/sgsn.h
@@ -10,7 +10,8 @@
enum sgsn_auth_policy {
SGSN_AUTH_POLICY_OPEN,
SGSN_AUTH_POLICY_CLOSED,
- SGSN_AUTH_POLICY_ACL_ONLY
+ SGSN_AUTH_POLICY_ACL_ONLY,
+ SGSN_AUTH_POLICY_REMOTE
};
struct sgsn_config {
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 71cd742df..525bfab11 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -187,6 +187,14 @@ void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm)
osmo_timer_del(&mm->timer);
}
+ /* Detach from subscriber which is possibly freed then */
+ if (mm->subscr) {
+ struct gsm_subscriber *subscr = mm->subscr;
+ mm->subscr = NULL;
+ subscr->mm = NULL;
+ gprs_subscr_delete(subscr);
+ }
+
/* Unlink from global list of MM contexts */
llist_del(&mm->list);
@@ -455,7 +463,24 @@ int sgsn_force_reattach_oldmsg(struct msgb *oldmsg)
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
struct gsm_subscriber *subscr)
{
- OSMO_ASSERT(mmctx);
+ if (!mmctx && subscr && strlen(subscr->imsi) > 0) {
+ mmctx = sgsn_mm_ctx_by_imsi(subscr->imsi);
+ OSMO_ASSERT(!mmctx || !mmctx->subscr || mmctx->subscr == subscr);
+ }
+
+ if (!mmctx) {
+ LOGP(DMM, LOGL_INFO,
+ "Subscriber data update for unregistered MM context, IMSI %s\n",
+ subscr->imsi);
+ return;
+ }
+
+ LOGMMCTXP(LOGL_INFO, mmctx, "Subscriber data update");
+
+ if (!subscr->mm && !mmctx->subscr) {
+ mmctx->subscr = subscr_get(subscr);
+ mmctx->subscr->mm = mmctx;
+ }
sgsn_auth_update(mmctx);
}
diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c
index eb85d45fb..071bdab84 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -22,6 +22,7 @@
#include <openbsc/sgsn.h>
#include <openbsc/gprs_sgsn.h>
#include <openbsc/gprs_gmm.h>
+#include <openbsc/gsm_subscriber.h>
#include <openbsc/debug.h>
@@ -101,6 +102,18 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx)
case SGSN_AUTH_POLICY_ACL_ONLY:
check_acl = 1;
break;
+
+ case SGSN_AUTH_POLICY_REMOTE:
+ if (!mmctx->subscr)
+ return mmctx->auth_state;
+
+ if (mmctx->subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING)
+ return mmctx->auth_state;
+
+ if (mmctx->subscr->authorized)
+ return SGSN_AUTH_ACCEPTED;
+
+ return SGSN_AUTH_REJECTED;
}
if (!strlen(mmctx->imsi)) {
@@ -126,7 +139,15 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx)
int sgsn_auth_request(struct sgsn_mm_ctx *mmctx)
{
- /* TODO: Add remote subscriber update requests here */
+ 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) {
+ LOGMMCTXP(LOGL_INFO, mmctx,
+ "Missing information, requesting subscriber data\n");
+ return 0;
+ }
+ }
sgsn_auth_update(mmctx);
@@ -136,12 +157,14 @@ int sgsn_auth_request(struct sgsn_mm_ctx *mmctx)
void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
{
enum sgsn_auth_state auth_state;
+ struct gsm_subscriber *subscr = mmctx->subscr;
LOGMMCTXP(LOGL_DEBUG, mmctx, "Updating authorization\n");
auth_state = sgsn_auth_state(mmctx);
- if (auth_state == SGSN_AUTH_UNKNOWN) {
- /* Reject requests since remote updates are NYI */
+ if (auth_state == SGSN_AUTH_UNKNOWN && subscr &&
+ !(subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING)) {
+ /* Reject requests if gprs_subscr_request_update fails */
LOGMMCTXP(LOGL_ERROR, mmctx,
"Missing information, authorization not possible\n");
auth_state = SGSN_AUTH_REJECTED;
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index 63816710e..5fb230f4c 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -45,6 +45,7 @@ const struct value_string sgsn_auth_pol_strs[] = {
{ SGSN_AUTH_POLICY_OPEN, "accept-all" },
{ SGSN_AUTH_POLICY_CLOSED, "closed" },
{ SGSN_AUTH_POLICY_ACL_ONLY, "acl-only" },
+ { SGSN_AUTH_POLICY_REMOTE, "remote" },
{ 0, NULL }
};
@@ -358,14 +359,15 @@ DEFUN(imsi_acl, cfg_imsi_acl_cmd,
}
DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
- "auth-policy (accept-all|closed|acl-only)",
+ "auth-policy (accept-all|closed|acl-only|remote)",
"Autorization Policy of SGSN\n"
"Accept all IMSIs (DANGEROUS)\n"
"Accept only home network subscribers or those in the ACL\n"
- "Accept only subscribers in the ACL\n")
+ "Accept only subscribers in the ACL\n"
+ "Use remote subscription data only (HLR)\n")
{
int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
- OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_ACL_ONLY);
+ OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
g_cfg->auth_policy = val;
return CMD_SUCCESS;
diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am
index 0e5d009e8..970311d0c 100644
--- a/openbsc/tests/sgsn/Makefile.am
+++ b/openbsc/tests/sgsn/Makefile.am
@@ -7,7 +7,8 @@ noinst_PROGRAMS = sgsn_test
sgsn_test_SOURCES = sgsn_test.c
sgsn_test_LDFLAGS = \
- -Wl,--wrap=sgsn_update_subscriber_data
+ -Wl,--wrap=sgsn_update_subscriber_data \
+ -Wl,--wrap=gprs_subscr_request_update
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 2eb6f388f..981a557ce 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -67,6 +67,14 @@ 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;
+
+int __wrap_gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
+ return (*subscr_request_update_cb)(mmctx);
+};
static int count(struct llist_head *head)
{
@@ -477,8 +485,6 @@ static void test_gmm_attach(void)
* again */
srand(1);
- sgsn_acl_add("123456789012345", &sgsn->cfg);
-
foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
/* Create a LLE/LLME */
@@ -537,8 +543,52 @@ static void test_gmm_attach(void)
OSMO_ASSERT(count(gprs_llme_list()) == 0);
ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
OSMO_ASSERT(!ictx);
+}
+
+static void test_gmm_attach_acl(void)
+{
+ const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
+ sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
+ sgsn_acl_add("123456789012345", &sgsn->cfg);
+ printf("Auth policy 'closed': ");
+ test_gmm_attach();
sgsn_acl_del("123456789012345", &sgsn->cfg);
+
+ sgsn->cfg.auth_policy = saved_auth_policy;
+}
+
+int my_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
+ int rc;
+ rc = __real_gprs_subscr_request_update(mmctx);
+ if (rc == -ENOTSUP) {
+ OSMO_ASSERT(mmctx->subscr);
+ gprs_subscr_update(mmctx->subscr);
+ }
+ return rc;
+};
+
+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 = gprs_subscr_get_or_create("123456789012345");
+ subscr->authorized = 1;
+ subscr_put(subscr);
+
+ printf("Auth policy 'remote': ");
+ 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;
}
/*
@@ -944,7 +994,8 @@ int main(int argc, char **argv)
test_gmm_detach_no_mmctx();
test_gmm_detach_accept_unexpected();
test_gmm_status_no_mmctx();
- test_gmm_attach();
+ test_gmm_attach_acl();
+ test_gmm_attach_subscr();
test_gmm_reject();
test_gmm_ptmsi_allocation();
printf("Done\n");
diff --git a/openbsc/tests/sgsn/sgsn_test.ok b/openbsc/tests/sgsn/sgsn_test.ok
index 1ee80be76..86dd0a211 100644
--- a/openbsc/tests/sgsn/sgsn_test.ok
+++ b/openbsc/tests/sgsn/sgsn_test.ok
@@ -5,7 +5,8 @@ Testing GMM detach (power off)
Testing GMM detach (no MMCTX)
Testing GMM detach accept (unexpected)
Testing GMM Status (no MMCTX)
-Testing GMM attach
+Auth policy 'closed': Testing GMM attach
+Auth policy 'remote': Testing GMM attach
Testing GMM reject
- Attach Request (invalid MI length)
- Attach Request (invalid MI type)
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 40053e30d..64437a19c 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -752,6 +752,9 @@ class TestVTYSGSN(TestVTYGenericBSC):
self.assertTrue(self.vty.verify('auth-policy closed', ['']))
res = self.vty.command("show running-config")
self.assert_(res.find('auth-policy closed') > 0)
+ self.assertTrue(self.vty.verify('auth-policy remote', ['']))
+ res = self.vty.command("show running-config")
+ self.assert_(res.find('auth-policy remote') > 0)
def add_nat_test(suite, workdir):
if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")):