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:
parent
e8b6968b12
commit
d04f7cc41b
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")):
|
||||
|
|
Loading…
Reference in New Issue