aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/gprs/gprs_gmm.c78
-rw-r--r--openbsc/src/gprs/gprs_sgsn.c8
-rw-r--r--openbsc/src/gprs/sgsn_auth.c73
3 files changed, 141 insertions, 18 deletions
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 95bf73b5a..a966949a4 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -642,24 +642,22 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
/* 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;
+ if (ctx->auth_state == SGSN_AUTH_UNKNOWN) {
+ /* Request authorization, this leads to a call to
+ * sgsn_update_subscriber_data which in turn calls
+ * gsm0408_gprs_access_granted or gsm0408_gprs_access_denied */
+
+ sgsn_auth_request(ctx, &sgsn->cfg);
+ /* Note that gsm48_gmm_authorize can be called recursively via
+ * sgsn_auth_request iff ctx->auth_info changes to AUTH_ACCEPTED
+ */
+ return 0;
+ }
+
+ if (ctx->auth_state != SGSN_AUTH_ACCEPTED) {
+ LOGMMCTXP(LOGL_NOTICE, ctx,
+ "authorization is denied, aborting procedure\n");
+ return -EACCES;
}
/* The MS is authorized */
@@ -689,6 +687,50 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
return 0;
}
+void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)
+{
+ switch (ctx->mm_state) {
+ case GMM_COMMON_PROC_INIT:
+ LOGP(DMM, LOGL_NOTICE,
+ "Authorized, continuing procedure, IMSI=%s\n",
+ ctx->imsi);
+ /* Continue with the authorization */
+ gsm48_gmm_authorize(ctx);
+ break;
+ default:
+ LOGP(DMM, LOGL_INFO,
+ "Authorized, ignored, IMSI=%s\n",
+ ctx->imsi);
+ }
+}
+
+void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx)
+{
+ switch (ctx->mm_state) {
+ case GMM_COMMON_PROC_INIT:
+ LOGP(DMM, LOGL_NOTICE,
+ "Not authorized, rejecting ATTACH REQUEST, IMSI=%s\n",
+ ctx->imsi);
+ gsm48_tx_gmm_att_rej(ctx, GMM_CAUSE_GPRS_NOTALLOWED);
+ mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJECT");
+ break;
+ case GMM_REGISTERED_NORMAL:
+ case GMM_REGISTERED_SUSPENDED:
+ LOGP(DMM, LOGL_NOTICE,
+ "Authorization lost, detaching, IMSI=%s\n",
+ ctx->imsi);
+ gsm48_tx_gmm_detach_req(
+ ctx, GPRS_DET_T_MT_REATT_NOTREQ, GMM_CAUSE_GPRS_NOTALLOWED);
+
+ mm_ctx_cleanup_free(ctx, "auth lost");
+ break;
+ default:
+ LOGP(DMM, LOGL_INFO,
+ "Authorization lost, ignored, IMSI=%s\n",
+ ctx->imsi);
+ }
+}
+
/* Parse Chapter 9.4.13 Identity Response */
static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
{
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index c4ff3c27d..daf9483bd 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -451,3 +451,11 @@ int sgsn_force_reattach_oldmsg(struct msgb *oldmsg)
return gsm0408_gprs_force_reattach_oldmsg(oldmsg);
}
+void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
+ struct sgsn_subscriber_data *sd)
+{
+ OSMO_ASSERT(mmctx);
+
+ if (sd->auth_state != mmctx->auth_state)
+ sgsn_auth_update(mmctx, sd);
+}
diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c
index 0a85934b0..e123909f2 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -21,6 +21,16 @@
#include <openbsc/sgsn.h>
#include <openbsc/gprs_sgsn.h>
+#include <openbsc/gprs_gmm.h>
+
+#include <openbsc/debug.h>
+
+const struct value_string auth_state_names[] = {
+ { SGSN_AUTH_ACCEPTED, "accepted"},
+ { SGSN_AUTH_REJECTED, "rejected"},
+ { SGSN_AUTH_UNKNOWN, "unknown"},
+ { 0, NULL }
+};
void sgsn_auth_init(struct sgsn_instance *sgi)
{
@@ -69,3 +79,66 @@ int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg)
return 0;
}
+enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx,
+ struct sgsn_config *cfg)
+{
+ char mccmnc[16];
+
+ OSMO_ASSERT(mmctx);
+
+ if (!sgsn->cfg.acl_enabled)
+ return SGSN_AUTH_ACCEPTED;
+
+ 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 (sgsn_acl_lookup(mmctx->imsi, &sgsn->cfg))
+ return SGSN_AUTH_ACCEPTED;
+
+ return SGSN_AUTH_REJECTED;
+}
+
+int sgsn_auth_request(struct sgsn_mm_ctx *mmctx, struct sgsn_config *cfg)
+{
+ struct sgsn_subscriber_data sd = {0};
+
+ sd.auth_state = sgsn_auth_state(mmctx, cfg);
+
+ if (sd.auth_state == SGSN_AUTH_UNKNOWN) {
+ LOGMMCTXP(LOGL_ERROR, mmctx,
+ "Missing information, authorization not possible\n");
+ sd.auth_state = SGSN_AUTH_REJECTED;
+ }
+
+ /* This will call sgsn_auth_update if auth_state has changed */
+ sgsn_update_subscriber_data(mmctx, &sd);
+ return 0;
+}
+
+void sgsn_auth_update(struct sgsn_mm_ctx *mmctx, struct sgsn_subscriber_data *sd)
+{
+ LOGMMCTXP(LOGL_INFO, mmctx, "Got authorization update: state %s\n",
+ get_value_string(auth_state_names, sd->auth_state));
+
+ mmctx->auth_state = sd->auth_state;
+
+ switch (sd->auth_state) {
+ case SGSN_AUTH_ACCEPTED:
+ gsm0408_gprs_access_granted(mmctx);
+ break;
+ case SGSN_AUTH_REJECTED:
+ gsm0408_gprs_access_denied(mmctx);
+ break;
+ default:
+ break;
+ }
+}