aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/msc/vlr.h10
-rw-r--r--src/libmsc/gsm_04_08.c18
-rw-r--r--src/libmsc/msc_a.c10
-rw-r--r--src/libvlr/vlr_auth_fsm.c11
-rw-r--r--src/libvlr/vlr_lu_fsm.c29
5 files changed, 58 insertions, 20 deletions
diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h
index d23661db0..c13fa21bf 100644
--- a/include/osmocom/msc/vlr.h
+++ b/include/osmocom/msc/vlr.h
@@ -288,6 +288,13 @@ static inline const char *vlr_ciph_name(enum vlr_ciph val)
return get_value_string(vlr_ciph_names, val);
}
+struct vlr_auth_ciph {
+ bool is_utran;
+ bool auth_required;
+ uint8_t a5_encryption_mask;
+ uint8_t uea_encryption_mask;
+};
+
/* Location Updating request */
struct osmo_fsm_inst *
vlr_loc_update(struct osmo_fsm_inst *parent,
@@ -298,8 +305,7 @@ vlr_loc_update(struct osmo_fsm_inst *parent,
enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
const struct osmo_location_area_id *old_lai,
const struct osmo_location_area_id *new_lai,
- bool authentication_required,
- bool ciphering_required,
+ const struct vlr_auth_ciph *auth_ciph,
uint8_t key_seq,
bool is_r99, bool is_utran,
bool assign_tmsi);
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index 9d3b5a216..dc43f7315 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -408,16 +408,28 @@ static int mm_rx_loc_upd_req(struct msc_a *msc_a, struct msgb *msg)
gsm48_decode_lai2(&lu->lai, &old_lai);
LOG_MSC_A_CAT(msc_a, DMM, LOGL_DEBUG, "USIM: old LAI: %s\n", osmo_lai_name(&old_lai));
+ is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU);
+
+ if (!is_utran && !net->a5_encryption_mask) {
+ LOG_MSC_A(msc_a, LOGL_ERROR, "No A5 algorithm is enabled (no A5/0, nor any A5/n > 0)\n");
+ return -ENOTSUP;
+ }
+ if (is_utran && !net->uea_encryption_mask) {
+ LOG_MSC_A(msc_a, LOGL_ERROR, "No UEA algorithm is enabled (no UEA0, nor any UEAn > 0)\n");
+ return -ENOTSUP;
+ }
+
msc_a_get(msc_a, __func__);
msc_a_get(msc_a, MSC_A_USE_LOCATION_UPDATING);
- is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU);
lu_fsm = vlr_loc_update(msc_a->c.fi,
MSC_A_EV_AUTHENTICATED, MSC_A_EV_CN_CLOSE, NULL,
net->vlr, msc_a, vlr_lu_type, tmsi, imsi,
&old_lai, &msc_a->via_cell.lai,
- is_utran || net->authentication_required,
- msc_a_require_ciphering(msc_a),
+ is_utran,
+ net->authentication_required,
+ net->a5_encryption_mask,
+ net->uea_encryption_mask,
lu->key_seq,
osmo_gsm48_classmark1_is_r99(&lu->classmark1),
is_utran,
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index 5135cf288..a595458c3 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -108,16 +108,6 @@ struct msc_a *msc_a_fi_priv(struct osmo_fsm_inst *fi)
return fi->priv;
}
-bool msc_a_require_ciphering(const struct msc_a *msc_a)
-{
- struct gsm_network *net = msc_a_net(msc_a);
- bool is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU);
- if (is_utran)
- return net->uea_encryption_mask > (1 << OSMO_UTRAN_UEA0);
- else
- return net->a5_encryption_mask > 0x1;
-}
-
static void update_counters(struct osmo_fsm_inst *fi, bool conn_accepted)
{
struct msc_a *msc_a = fi->priv;
diff --git a/src/libvlr/vlr_auth_fsm.c b/src/libvlr/vlr_auth_fsm.c
index a6b5cd271..dad7db61b 100644
--- a/src/libvlr/vlr_auth_fsm.c
+++ b/src/libvlr/vlr_auth_fsm.c
@@ -49,6 +49,7 @@ struct auth_fsm_priv {
bool is_r99;
bool is_utran;
bool auth_requested;
+ bool auth_mandatory;
int auth_tuple_max_reuse_count; /* see vlr->cfg instead */
};
@@ -344,6 +345,12 @@ static void auth_fsm_wait_ai(struct osmo_fsm_inst *fi, uint32_t event,
|| (event == VLR_AUTH_E_HLR_SAI_NACK &&
gsup->cause != GMM_CAUSE_IMSI_UNKNOWN)
|| (event == VLR_AUTH_E_HLR_SAI_ABORT)) {
+ /* We have no auth tuples. If Authentication is optional i.e. A5/0 is allowed, continue without
+ * authentication. */
+ if (!afp->auth_mandatory) {
+
+ }
+
if (vsub->vlr->cfg.auth_reuse_old_sets_on_error
&& vlr_subscr_has_auth_tuple(vsub, -1)) {
/* To re-use an old tuple, disable the max_reuse_count
@@ -595,7 +602,8 @@ struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub,
struct osmo_fsm_inst *parent,
uint32_t parent_term_event,
bool is_r99,
- bool is_utran)
+ bool is_utran,
+ bool auth_mandatory)
{
struct osmo_fsm_inst *fi;
struct auth_fsm_priv *afp;
@@ -618,6 +626,7 @@ struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub,
afp->by_imsi = true;
afp->is_r99 = is_r99;
afp->is_utran = is_utran;
+ afp->auth_mandatory = auth_mandatory || is_utran;
fi->priv = afp;
vsub->auth_fsm = fi;
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
index f67331674..911749b5c 100644
--- a/src/libvlr/vlr_lu_fsm.c
+++ b/src/libvlr/vlr_lu_fsm.c
@@ -676,6 +676,7 @@ struct lu_fsm_priv {
struct osmo_location_area_id old_lai;
struct osmo_location_area_id new_lai;
bool authentication_required;
+ uint8_t a5_encryption_mask;
bool ciphering_required;
uint8_t key_seq;
bool is_r99;
@@ -1465,6 +1466,21 @@ static inline struct lu_fsm_priv *lu_fsm_fi_priv(struct osmo_fsm_inst *fi)
return (struct lu_fsm_priv*)fi->priv;
}
+static bool require_ciphering(const struct vlr_auth_ciph *auth_ciph)
+{
+ if (auth_ciph->is_utran)
+ return (auth_ciph->uea_encryption_mask && (1 << OSMO_UTRAN_UEA0)) == 0;
+ else
+ return (auth_ciph->a5_encryption_mask & GSM0808_ALG_ID_A5_0) == 0;
+}
+
+static bool require_auth(const struct vlr_auth_ciph *auth_ciph)
+{
+ if (auth_ciph->is_utran)
+ return true;
+ return require_ciphering(auth_ciph);
+}
+
struct osmo_fsm_inst *
vlr_loc_update(struct osmo_fsm_inst *parent,
uint32_t parent_event_success,
@@ -1474,19 +1490,23 @@ vlr_loc_update(struct osmo_fsm_inst *parent,
enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
const struct osmo_location_area_id *old_lai,
const struct osmo_location_area_id *new_lai,
- bool authentication_required,
- bool ciphering_required,
+ const struct vlr_auth_ciph *auth_ciph,
uint8_t key_seq,
bool is_r99, bool is_utran,
bool assign_tmsi)
{
struct osmo_fsm_inst *fi;
struct lu_fsm_priv *lfp;
+ const char *auth_ciph_str;
fi = osmo_fsm_inst_alloc_child(&vlr_lu_fsm, parent, parent_event_failure);
if (!fi)
return NULL;
+ /* If A5/0 is not permitted, authentication is required. */
+ if (!(a5_encryption_mask & GSM0808_ALG_ID_A5_0))
+ authentication_required = true;
+
lfp = talloc_zero(fi, struct lu_fsm_priv);
lfp->vlr = vlr;
lfp->msc_conn_ref = msc_conn_ref;
@@ -1498,8 +1518,7 @@ vlr_loc_update(struct osmo_fsm_inst *parent,
lfp->parent_event_success = parent_event_success;
lfp->parent_event_failure = parent_event_failure;
lfp->parent_event_data = parent_event_data;
- lfp->authentication_required = authentication_required;
- lfp->ciphering_required = ciphering_required;
+ lfp->auth_ciph = *auth_ciph;
lfp->key_seq = key_seq;
lfp->is_r99 = is_r99;
lfp->is_utran = is_utran;
@@ -1511,6 +1530,8 @@ vlr_loc_update(struct osmo_fsm_inst *parent,
}
fi->priv = lfp;
+ if (authentication_required || (a5_encryption_mask & GSM0808_ALG_ID_A5_0) == 0) {
+ }
LOGPFSM(fi, "rev=%s net=%s%s%s\n",
is_r99 ? "R99" : "GSM",
is_utran ? "UTRAN" : "GERAN",