sgsn: Add 'acl-only' authentication policy

Currently the VTY 'auth-policy' command results in setting or clearing
the acl_enabled flag. This also enables the matching of the MCC/MNC
prefix of the IMSI.

This patch adds an additional policy 'acl-only' which disables the
MCC/MNC matching and relies on the ACL only.

Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2014-11-04 10:08:37 +01:00 committed by Holger Hans Peter Freyther
parent ca1c7aa5e9
commit d7b7773d1b
6 changed files with 65 additions and 18 deletions

View File

@ -7,6 +7,12 @@
#include <osmocom/gprs/gprs_ns.h>
#include <openbsc/gprs_sgsn.h>
enum sgsn_auth_policy {
SGSN_AUTH_POLICY_OPEN,
SGSN_AUTH_POLICY_CLOSED,
SGSN_AUTH_POLICY_ACL_ONLY
};
struct sgsn_config {
/* parsed from config file */
@ -16,7 +22,7 @@ struct sgsn_config {
/* misc */
struct gprs_ns_inst *nsi;
int acl_enabled;
enum sgsn_auth_policy auth_policy;
struct llist_head imsi_acl;
};

View File

@ -83,25 +83,41 @@ enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx,
struct sgsn_config *cfg)
{
char mccmnc[16];
int check_net = 0;
int check_acl = 0;
OSMO_ASSERT(mmctx);
if (!sgsn->cfg.acl_enabled)
switch (sgsn->cfg.auth_policy) {
case SGSN_AUTH_POLICY_OPEN:
return SGSN_AUTH_ACCEPTED;
case SGSN_AUTH_POLICY_CLOSED:
check_net = 1;
check_acl = 1;
break;
case SGSN_AUTH_POLICY_ACL_ONLY:
check_acl = 1;
break;
}
if (!strlen(mmctx->imsi)) {
LOGMMCTXP(LOGL_NOTICE, mmctx,
"Missing IMSI, authorization state not known\n");
return SGSN_AUTH_UNKNOWN;
}
/* As a temorary hack, we simply assume that the IMSI exists,
* as long as it is part of 'our' network */
snprintf(mccmnc, sizeof(mccmnc), "%03d%02d", mmctx->ra.mcc, mmctx->ra.mnc);
if (strncmp(mccmnc, mmctx->imsi, 5) == 0)
return SGSN_AUTH_ACCEPTED;
if (check_net) {
/* We simply assume that the IMSI exists, as long as it is part
* of 'our' network */
snprintf(mccmnc, sizeof(mccmnc), "%03d%02d",
mmctx->ra.mcc, mmctx->ra.mnc);
if (strncmp(mccmnc, mmctx->imsi, 5) == 0)
return SGSN_AUTH_ACCEPTED;
}
if (sgsn_acl_lookup(mmctx->imsi, &sgsn->cfg))
if (check_acl && sgsn_acl_lookup(mmctx->imsi, &sgsn->cfg))
return SGSN_AUTH_ACCEPTED;
return SGSN_AUTH_REJECTED;

View File

@ -78,7 +78,7 @@ static struct sgsn_instance sgsn_inst = {
.config_file = "osmo_sgsn.cfg",
.cfg = {
.gtp_statedir = "./",
.acl_enabled = 1,
.auth_policy = SGSN_AUTH_POLICY_CLOSED,
},
};
struct sgsn_instance *sgsn = &sgsn_inst;

View File

@ -41,6 +41,14 @@
static struct sgsn_config *g_cfg = NULL;
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" },
{ 0, NULL }
};
#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
static char *gprs_apn2str(uint8_t *apn, unsigned int len)
{
@ -127,7 +135,8 @@ static int config_write_sgsn(struct vty *vty)
}
vty_out(vty, " auth-policy %s%s",
g_cfg->acl_enabled ? "closed" : "accept-all", VTY_NEWLINE);
get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
VTY_NEWLINE);
llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
@ -349,15 +358,15 @@ DEFUN(imsi_acl, cfg_imsi_acl_cmd,
}
DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
"auth-policy (accept-all|closed)",
"auth-policy (accept-all|closed|acl-only)",
"Autorization Policy of SGSN\n"
"Accept all IMSIs (DANGEROUS\n"
"Accept only home network subscribers or those in ACL\n")
"Accept all IMSIs (DANGEROUS)\n"
"Accept only home network subscribers or those in the ACL\n"
"Accept only subscribers in the ACL\n")
{
if (!strcmp(argv[0], "accept-all"))
g_cfg->acl_enabled = 0;
else
g_cfg->acl_enabled = 1;
int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_ACL_ONLY);
g_cfg->auth_policy = val;
return CMD_SUCCESS;
}

View File

@ -41,7 +41,7 @@ static struct sgsn_instance sgsn_inst = {
.config_file = "osmo_sgsn.cfg",
.cfg = {
.gtp_statedir = "./",
.acl_enabled = 1,
.auth_policy = SGSN_AUTH_POLICY_CLOSED,
},
};
struct sgsn_instance *sgsn = &sgsn_inst;

View File

@ -722,6 +722,22 @@ class TestVTYSGSN(TestVTYGenericBSC):
res = self.vty.command("show llc")
self.assert_(res.find('State of LLC Entities') >= 0)
def testVtyAuth(self):
self.vty.enable()
self.assertTrue(self.vty.verify('configure terminal', ['']))
self.assertEquals(self.vty.node(), 'config')
self.assertTrue(self.vty.verify('sgsn', ['']))
self.assertEquals(self.vty.node(), 'config-sgsn')
self.assertTrue(self.vty.verify('auth-policy accept-all', ['']))
res = self.vty.command("show running-config")
self.assert_(res.find('auth-policy accept-all') > 0)
self.assertTrue(self.vty.verify('auth-policy acl-only', ['']))
res = self.vty.command("show running-config")
self.assert_(res.find('auth-policy acl-only') > 0)
self.assertTrue(self.vty.verify('auth-policy closed', ['']))
res = self.vty.command("show running-config")
self.assert_(res.find('auth-policy closed') > 0)
def add_nat_test(suite, workdir):
if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")):
print("Skipping the NAT test")