aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c82
1 files changed, 64 insertions, 18 deletions
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index e89286eb5..515ff84ba 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -320,8 +320,14 @@ static bool authorize_subscriber(struct gsm_loc_updating_operation *loc,
* phones will not send us the information and we will have to check
* what we want to do with that.
*/
- if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
+ if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei)) {
+ LOGP(DMM, LOGL_DEBUG, "authorize_subscriber() failed:"
+ " still waiting for%s%s of subscriber %s\n",
+ loc->waiting_for_imsi? " IMSI": "",
+ loc->waiting_for_imei? " IMEI": "",
+ subscr_name(subscriber));
return false;
+ }
switch (subscriber->group->net->auth_policy) {
case GSM_AUTH_POLICY_CLOSED:
@@ -411,10 +417,6 @@ static int _gsm0408_authorize_sec_cb(unsigned int hooknum, unsigned int event,
int rc = 0;
switch (event) {
- case GSM_SECURITY_AUTH_FAILED:
- release_loc_updating_req(conn, 1);
- break;
-
case GSM_SECURITY_ALREADY:
LOGP(DMM, LOGL_ERROR, "We don't expect LOCATION "
"UPDATING after CM SERVICE REQUEST\n");
@@ -425,22 +427,40 @@ static int _gsm0408_authorize_sec_cb(unsigned int hooknum, unsigned int event,
rc = finish_lu(conn);
break;
+ case GSM_SECURITY_AUTH_FAILED:
+ /*
+ * gsm48_secure_channel() will pass only
+ * GSM_SECURITY_NOAVAIL in case of failure. If future
+ * code should add a GSM_SECURITY_AUTH_FAILED status in
+ * this code path, letting the Location Update time out
+ * will do all necessary error messaging and logging,
+ * see loc_upd_rej_cb().
+ */
+ LOGP(DMM, LOGL_ERROR,
+ "Authorization failed for subscriber %s\n",
+ subscr_name(conn->subscr));
+ rc = -1;
+ break;
+
default:
+ LOGP(DMM, LOGL_DEBUG, "invalid authorization event\n");
rc = -EINVAL;
};
return rc;
}
-static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg)
+int gsm0408_authorize(struct gsm_subscriber_connection *conn)
{
- if (!conn->loc_operation)
+ if (!conn->loc_operation) {
+ LOGP(DMM, LOGL_DEBUG, "gsm0408_authorize() failed:"
+ " no location update operation pending\n");
return 0;
+ }
if (authorize_subscriber(conn->loc_operation, conn->subscr))
- return gsm48_secure_channel(conn,
- conn->loc_operation->key_seq,
- _gsm0408_authorize_sec_cb, NULL);
+ return gsm48_secure_channel(conn, conn->loc_operation->key_seq,
+ _gsm0408_authorize_sec_cb, NULL);
return 0;
}
@@ -625,7 +645,7 @@ static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *ms
}
/* Check if we can let the mobile station enter */
- return gsm0408_authorize(conn, msg);
+ return gsm0408_authorize(conn);
}
@@ -754,7 +774,7 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb
/* check if we can let the subscriber into our network immediately
* or if we need to wait for identity responses. */
- return gsm0408_authorize(conn, msg);
+ return gsm0408_authorize(conn);
}
/* Turn int into semi-octet representation: 98 => 0x89 */
@@ -1154,6 +1174,7 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_auth_resp *ar = (struct gsm48_auth_resp*) gh->data;
struct gsm_network *net = conn->network;
+ gsm_cbfn *cb;
DEBUGP(DMM, "MM AUTHENTICATION RESPONSE (sres = %s): ",
osmo_hexdump(ar->sres, 4));
@@ -1164,11 +1185,11 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct
return -EIO;
}
+ cb = conn->sec_operation->cb;
+
/* Validate SRES */
if (memcmp(conn->sec_operation->atuple.vec.sres, ar->sres,4)) {
int rc;
- gsm_cbfn *cb = conn->sec_operation->cb;
-
DEBUGPC(DMM, "Invalid (expected %s)\n",
osmo_hexdump(conn->sec_operation->atuple.vec.sres, 4));
@@ -1183,10 +1204,35 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct
DEBUGPC(DMM, "OK\n");
- /* Start ciphering */
- return msc_gsm0808_tx_cipher_mode(conn, net->a5_encryption,
- conn->sec_operation->atuple.vec.kc,
- 8, 0);
+ /* TODO separate enable flags and/or A5 algos for auth and encryption */
+ if (net->a5_encryption)
+ /* Start ciphering */
+ /* TODO gsm0808_cipher_mode() is still a dummy, and no code
+ * to receive a Ciphering Mode Complete exists in the MSC.
+ * As soon as such a receiver exists, it must call
+ * iu_tx_sec_mode_cmd() as below. */
+ return msc_gsm0808_tx_cipher_mode(conn, net->a5_encryption,
+ conn->sec_operation->atuple.vec.kc,
+ 8, 0);
+
+ if (conn->via_iface == IFACE_IU
+ && !conn->iu.integrity_protection) {
+ LOGP(DIUCS, LOGL_DEBUG,
+ "Requesting integrity protection for %s\n",
+ subscr_name(conn->subscr));
+
+ /* send Security Mode Command (IK) to start integrity
+ * protection */
+ return iu_tx_sec_mode_cmd(conn->iu.ue_ctx,
+ &conn->sec_operation->atuple, 0, 1);
+ }
+
+ /* Only authentication requested, and we're done. */
+ if (cb)
+ cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_SUCCEEDED, NULL,
+ conn, conn->sec_operation->cb_data);
+ release_security_operation(conn);
+ return 0;
}
/* Receive a GSM 04.08 Mobility Management (MM) message */