sgsn: Move IMSI authorization to gsm48_gmm_authorize

Currently the IMSI is only checked immediately when an Attach Request
is received that contains an IMSI IE. If it contains a P-TMSI
instead, access is always granted.

This commit moves the IMSI check to gsm48_gmm_authorize where it is
applied when IMSI and IMEI have been acquired. This fixes the
authorization when the Attach Accept doesn't contain an IMSI.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 75797db..af21ead 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -117,6 +117,8 @@
 	 * (refers to the timer) and pending_req (refers to the procedure),
 	 * where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
 	 * whether one of them can be dropped. */
+
+	int			is_authorized;
 };
 
 #define LOGMMCTXP(level, mm, fmt, args...) \
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 575ad79..95bf73b 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -640,9 +640,30 @@
 	}
 
 	/* All information required for authentication is available */
-
 	ctx->t3370_id_type = GSM_MI_TYPE_NONE;
 
+	if (!ctx->is_authorized) {
+		/* As a temorary hack, we simply assume that the IMSI exists,
+		 * as long as it is part of 'our' network */
+		char mccmnc[16];
+		int rc;
+		snprintf(mccmnc, sizeof(mccmnc), "%03d%02d",
+			 ctx->ra.mcc, ctx->ra.mnc);
+		if (strncmp(mccmnc, ctx->imsi, 5) &&
+		    (sgsn->cfg.acl_enabled &&
+		     !sgsn_acl_lookup(ctx->imsi, &sgsn->cfg))) {
+			LOGP(DMM, LOGL_NOTICE, "Rejecting ATTACH REQUEST IMSI=%s\n",
+			     ctx->imsi);
+			rc = gsm48_tx_gmm_att_rej(ctx,
+						  GMM_CAUSE_GPRS_NOTALLOWED);
+			mm_ctx_cleanup_free(ctx, "ATTACH REJECT");
+			return rc;
+		}
+		ctx->is_authorized = 1;
+	}
+
+	/* The MS is authorized */
+
 	switch (ctx->pending_req) {
 	case 0:
 		LOGMMCTXP(LOGL_INFO, ctx,
@@ -799,18 +820,6 @@
 #if 0
 			return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
 #else
-			/* As a temorary hack, we simply assume that the IMSI exists,
-			 * as long as it is part of 'our' network */
-			char mccmnc[16];
-			snprintf(mccmnc, sizeof(mccmnc), "%03d%02d", ra_id.mcc, ra_id.mnc);
-			if (strncmp(mccmnc, mi_string, 5) &&
-			    (sgsn->cfg.acl_enabled &&
-			     !sgsn_acl_lookup(mi_string, &sgsn->cfg))) {
-				LOGP(DMM, LOGL_NOTICE, "Rejecting ATTACH REQUEST IMSI=%s\n",
-				     mi_string);
-				return gsm48_tx_gmm_att_rej_oldmsg(msg,
-								GMM_CAUSE_GPRS_NOTALLOWED);
-			}
 			ctx = sgsn_mm_ctx_alloc(0, &ra_id);
 			if (!ctx)
 				return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_NET_FAIL);
diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c
index 49ee2df..218092f 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -340,6 +340,8 @@
 	/* reset the PRNG used by sgsn_alloc_ptmsi */
 	srand(1);
 
+	sgsn_acl_add("123456789012345", &sgsn->cfg);
+
 	foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
 
 	/* Create a LLE/LLME */
@@ -369,9 +371,6 @@
 	send_0408_message(ctx->llme, foreign_tlli,
 			  ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
 
-	/* FIXME: We are not authorized and should get an Attach Reject, fix
-	 * authorization in gprs_gmm.c */
-
 	/* check that the MM context has not been removed due to a failed
 	 * authorization */
 	OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
@@ -401,6 +400,8 @@
 	OSMO_ASSERT(count(gprs_llme_list()) == 0);
 	ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
 	OSMO_ASSERT(!ictx);
+
+	sgsn_acl_del("123456789012345", &sgsn->cfg);
 }
 
 static struct log_info_cat gprs_categories[] = {