diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 49d5407..bf18ea1 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -12,7 +12,6 @@
 
 #include <openbsc/gsm_data.h>
 
-#define GSM_IMSI_LENGTH 17
 #define GSM_IMEI_LENGTH 17
 #define GSM_EXTENSION_LENGTH 15
 #define GSM_APN_LENGTH 102
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 593a86f..4844412 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -8,6 +8,8 @@
 
 #include <openbsc/rest_octets.h>
 
+#define GSM_IMSI_LENGTH 17
+
 /** annotations for msgb ownership */
 #define __uses
 
@@ -21,6 +23,7 @@ struct gsm_subscriber_group;
 enum gsm_subscr_ext_alloc_policy {
 	GSM_SUBSCR_DONT_CREATE = 0,
 	GSM_SUBSCR_RANDOM_EXT = 1,
+	GSM_SUBSCR_MATCH_PREF = 2,
 };
 
 enum gsm_security_event {
@@ -206,6 +209,7 @@ enum gsm_auth_policy {
 	GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */
 	GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */
 	GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */
+	GSM_AUTH_POLICY_PREFIX, /* accept IMSIs with a given prefix */
 };
 
 #define GSM_T3101_DEFAULT 10
@@ -220,6 +224,7 @@ struct gsm_network {
 	char *name_long;
 	char *name_short;
 	enum gsm_auth_policy auth_policy;
+	char auth_prefix[GSM_IMSI_LENGTH];
 	enum gsm48_reject_value reject_cause;
 	int a5_encryption;
 	int neci;
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 7d6c776..7108bff 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -5,7 +5,6 @@
 #include <osmocom/core/linuxlist.h>
 
 #define GSM_IMEI_LENGTH 17
-#define GSM_IMSI_LENGTH 17
 #define GSM_NAME_LENGTH 160
 
 #define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index b928738..dfcca24 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -189,8 +189,11 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
 		net->name_long, VTY_NEWLINE);
 	vty_out(vty, "  Short network name: '%s'%s",
 		net->name_short, VTY_NEWLINE);
-	vty_out(vty, "  Authentication policy: %s%s",
-		gsm_auth_policy_name(net->auth_policy), VTY_NEWLINE);
+	vty_out(vty, "  Authentication policy: %s",
+		gsm_auth_policy_name(net->auth_policy));
+	if (net->auth_prefix[0] != '\0')
+		vty_out(vty, ", authorized prefix: %s", net->auth_prefix);
+	vty_out(vty, "%s", VTY_NEWLINE);
 	vty_out(vty, "  Location updating reject cause: %u%s",
 		net->reject_cause, VTY_NEWLINE);
 	vty_out(vty, "  Encryption: A5/%u%s", net->a5_encryption,
@@ -776,6 +779,8 @@ static int config_write_net(struct vty *vty)
 	vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
 	vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
 	vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE);
+	if (gsmnet->auth_prefix[0] != '\0')
+		vty_out(vty, " authorize-prefix %s%s", gsmnet->auth_prefix, VTY_NEWLINE);
 	vty_out(vty, " location updating reject cause %u%s",
 		gsmnet->reject_cause, VTY_NEWLINE);
 	vty_out(vty, " encryption a5 %u%s", gsmnet->a5_encryption, VTY_NEWLINE);
@@ -1384,11 +1389,12 @@ DEFUN(cfg_net_name_long,
 
 DEFUN(cfg_net_auth_policy,
       cfg_net_auth_policy_cmd,
-      "auth policy (closed|accept-all|token)",
+      "auth policy (closed|accept-all|prefix|token)",
 	"Authentication (not cryptographic)\n"
 	"Set the GSM network authentication policy\n"
 	"Require the MS to be activated in HLR\n"
 	"Accept all MS, whether in HLR or not\n"
+      "Use IMSI prefix for authorization decision\n"
 	"Use SMS-token based authentication\n")
 {
 	enum gsm_auth_policy policy = gsm_auth_policy_parse(argv[0]);
@@ -1399,6 +1405,20 @@ DEFUN(cfg_net_auth_policy,
 	return CMD_SUCCESS;
 }
 
+/* Note: limit on the prefix length is set by internal vty code limitations */
+DEFUN(cfg_net_authorize_prefix, cfg_net_authorize_prefix_cmd,
+      "authorize-prefix <0-9999999999>",
+      "Set IMSI prefix which will be used for authorization decision\n"
+      "PREFIX of IMSIs which are allowed to use the network\n")
+{
+	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
+	strncpy(gsmnet->auth_prefix, argv[0], GSM_IMSI_LENGTH);
+	gsmnet->auth_prefix[GSM_IMSI_LENGTH - 1] = '\0';
+
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_net_reject_cause,
       cfg_net_reject_cause_cmd,
       "location updating reject cause <2-111>",
@@ -3912,6 +3932,7 @@ int bsc_vty_init(const struct log_info *cat)
 	install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
 	install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
 	install_element(GSMNET_NODE, &cfg_net_auth_policy_cmd);
+	install_element(GSMNET_NODE, &cfg_net_authorize_prefix_cmd);
 	install_element(GSMNET_NODE, &cfg_net_reject_cause_cmd);
 	install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
 	install_element(GSMNET_NODE, &cfg_net_neci_cmd);
diff --git a/openbsc/src/libbsc/net_init.c b/openbsc/src/libbsc/net_init.c
index 00a8a9b..ed23f33 100644
--- a/openbsc/src/libbsc/net_init.c
+++ b/openbsc/src/libbsc/net_init.c
@@ -54,6 +54,7 @@ struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_cod
 	net->network_code = network_code;
 	net->num_bts = 0;
 	net->reject_cause = GSM48_REJECT_ROAMING_NOT_ALLOWED;
+	net->auth_prefix[GSM_IMSI_LENGTH - 1] = '\0';
 	net->T3101 = GSM_T3101_DEFAULT;
 	net->T3105 = GSM_T3105_DEFAULT;
 	net->T3113 = GSM_T3113_DEFAULT;
diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c
index 242c014..4b4be42 100644
--- a/openbsc/src/libcommon/gsm_data.c
+++ b/openbsc/src/libcommon/gsm_data.c
@@ -161,6 +161,7 @@ static const struct value_string auth_policy_names[] = {
 	{ GSM_AUTH_POLICY_CLOSED,	"closed" },
 	{ GSM_AUTH_POLICY_ACCEPT_ALL,	"accept-all" },
 	{ GSM_AUTH_POLICY_TOKEN,	"token" },
+	{ GSM_AUTH_POLICY_PREFIX,	"prefix" },
 	{ 0,				NULL }
 };
 
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index bb1b49a..ab950c7 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <time.h>
 #include <netinet/in.h>
@@ -244,8 +245,15 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
 	return -EINVAL; /* not reached */
 }
 
+static bool subscr_prefix_check(const char *auth_prefix, const char *imsi)
+{
+	return (strncmp(imsi, auth_prefix, strnlen(auth_prefix,
+						   GSM_IMSI_LENGTH)) == 0);
+}
+
 static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
-				struct gsm_subscriber *subscriber)
+				struct gsm_subscriber *subscriber,
+				const char *auth_prefix)
 {
 	if (!subscriber)
 		return 0;
@@ -261,6 +269,10 @@ static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
 	switch (subscriber->group->net->auth_policy) {
 	case GSM_AUTH_POLICY_CLOSED:
 		return subscriber->authorized;
+	case GSM_AUTH_POLICY_PREFIX:
+		if (subscriber->authorized)
+			return 1;
+		return subscr_prefix_check(auth_prefix, subscriber->imsi);
 	case GSM_AUTH_POLICY_TOKEN:
 		if (subscriber->authorized)
 			return subscriber->authorized;
@@ -366,7 +378,8 @@ static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb
 	if (!conn->loc_operation)
 		return 0;
 
-	if (authorize_subscriber(conn->loc_operation, conn->subscr))
+	if (authorize_subscriber(conn->loc_operation, conn->subscr,
+				 conn->bts->network->auth_prefix))
 		return gsm48_secure_channel(conn,
 			conn->loc_operation->key_seq,
 			_gsm0408_authorize_sec_cb, NULL);
@@ -513,6 +526,10 @@ static struct gsm_subscriber *subscr_create(const struct gsm_network *net,
 	if (GSM_SUBSCR_DONT_CREATE == net->create_subscriber)
 		return NULL;
 
+	if (net->create_subscriber & GSM_SUBSCR_MATCH_PREF)
+		if (!subscr_prefix_check(net->auth_prefix, imsi))
+			return NULL;
+
 	return subscr_create_subscriber(net->subscr_group, imsi);
 }
 
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index 4dd0573..0ac2e90 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -1032,11 +1032,15 @@ DEFUN(cfg_nitb, cfg_nitb_cmd,
 }
 
 DEFUN(cfg_nitb_subscr_create, cfg_nitb_subscr_create_cmd,
-      "subscriber-create-on-demand",
-      "Make a new record when a subscriber is first seen.\n")
+      "subscriber-create-on-demand [imsi-prefix]",
+      "Make a new record when a subscriber is first seen.\n"
+      "Create subscribers only if IMSI matches the prefix specified in "
+      "authorize-prefix command \n")
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
 	gsmnet->create_subscriber = GSM_SUBSCR_RANDOM_EXT;
+	if (argc)
+		gsmnet->create_subscriber |= GSM_SUBSCR_MATCH_PREF;
 	return CMD_SUCCESS;
 }
 
@@ -1070,9 +1074,13 @@ DEFUN(cfg_nitb_no_assign_tmsi, cfg_nitb_no_assign_tmsi_cmd,
 static int config_write_nitb(struct vty *vty)
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	const char *pref = gsmnet->create_subscriber ? "" : "no ",
+		*ims = (gsmnet->create_subscriber & GSM_SUBSCR_MATCH_PREF) ?
+		" imsi-prefix" : "";
+
 	vty_out(vty, "nitb%s", VTY_NEWLINE);
-	vty_out(vty, " %ssubscriber-create-on-demand%s",
-		gsmnet->create_subscriber ? "" : "no ", VTY_NEWLINE);
+	vty_out(vty, " %ssubscriber-create-on-demand%s%s",
+		pref, ims, VTY_NEWLINE);
 	vty_out(vty, " %sassign-tmsi%s",
 		gsmnet->avoid_tmsi ? "no " : "", VTY_NEWLINE);
 	return CMD_SUCCESS;
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index c088855..e240811 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -231,6 +231,20 @@ class TestVTYNITB(TestVTYGenericBSC):
 
         self.assertEquals(self.vty.node(), 'config-mncc-int')
 
+    def testVtyAuthorization(self):
+        self.vty.enable()
+        self.vty.command("configure terminal")
+        self.vty.command("network")
+        self.assertTrue(self.vty.verify("auth policy closed", ['']))
+        self.assertTrue(self.vty.verify("auth policy prefix", ['']))
+        self.assertTrue(self.vty.verify("authorize-prefix 220380", ['']))
+        self.vty.command("end")
+        self.vty.command("configure terminal")
+        self.vty.command("nitb")
+        self.assertTrue(self.vty.verify("subscriber-create-on-demand", ['']))
+        self.assertTrue(self.vty.verify("subscriber-create-on-demand imsi-prefix", ['']))
+        self.vty.command("end")
+
     def testSi2Q(self):
         self.vty.enable()
         self.vty.command("configure terminal")
