diff options
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/gprs/gprs_gmm.c | 78 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_sgsn.c | 8 | ||||
-rw-r--r-- | openbsc/src/gprs/sgsn_auth.c | 73 |
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; + } +} |