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
This commit is contained in:
Jacob Erlbeck 2014-11-12 10:18:09 +01:00 committed by Holger Hans Peter Freyther
parent e8b6968b12
commit d04f7cc41b
8 changed files with 120 additions and 13 deletions

View File

@ -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 {

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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 \

View File

@ -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");

View File

@ -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)

View File

@ -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")):