aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/sgsn_auth.c
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-10-24 18:09:54 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-11-14 09:58:28 +0100
commit423f8bfa027d544867dcf7afc188a8ea5221e2bc (patch)
tree1a757951e6e28872c05e47c0bd25b50845e2de42 /openbsc/src/gprs/sgsn_auth.c
parent0c06f98ced2b70801147eb52d6596079e473dfc9 (diff)
sgsn: Make authorization asynchronous
Currently the authorization of an IMSI is done by checking ACLs synchronously which is not feasible when the subscriber data has to be retrieved from an external source. This patch changes this by using a callback when the information is available. This is also done when only ACL are checked, in this case the callback is invoked from within sgsn_auth_request(). The callback function sgsn_update_subscriber_data calls sgsn_auth_update which in turn calls either gsm0408_gprs_access_granted or gsm0408_gprs_access_denied. gsm48_gmm_authorize is extended by a call to sgsn_auth_request when IMSI and IMEI are available but the auth_state is unknown. The change has been successfully tested with single phones (E71 and IPhone 5c). Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/src/gprs/sgsn_auth.c')
-rw-r--r--openbsc/src/gprs/sgsn_auth.c73
1 files changed, 73 insertions, 0 deletions
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;
+ }
+}