fix error on BSSMAP Cipher Mode Complete L3 msg IE

When an MS returns the IMEISV in the BSSMAP Cipher Mode Complete message in
the Layer 3 Message Contents IE, do not re-invoke the decode_cb() a second
time, but instead point to it from the ran_msg.cipher_mode_complete struct.

When the MSC-A decodes the Ciphering Mode Complete message, it always wants to
also decode the enclosed DTAP from the Layer 3 Message Contents IE. However,
when the MSC-I preliminarily decodes messages, it often just wants to identify
specific messages without fully acting on them, let alone dispatching RAN_UP_L2
events more than once. So leave it up to the supplied decode_cb passed to
ran_dec_l2() implementations to decide whether to decode the DTAP.

In msc_a.c hence evaluate the DTAP by passing a msgb to msc_a_up_l3(), which
will evaluate the RR Ciphering Mode Complete message found in the BSSMAP Cipher
Mode Complete's Layer 3 Message Contents IE.

Particularly, the previous choice of calling the decode_cb a second time for
the enclosed DTAP caused a header/length parsing error: the second decode_cb
call tried to mimick DTAP by overwriting the l3h pointer and truncating the
length of the msgb, but subsequently ran_a_decode_l2() would again derive the
l3h from the l2h, obliterating the intended re-interpretation as DTAP, and
hence the previous truncation caused error messages on each and every Cipher
Mode Complete message, like:

DBSSAP ERROR libmsc/ran_msg_a.c:764 msc_a(IMSI-26242340300XXXX:MSISDN-XXXX:TMSI-0xA73E055A:GERAN-A-77923:LU)[0x5563947521e0]{MSC_A_ST_AUTH_CIPH}: RAN decode: BSSMAP: BSSMAP data truncated, discarding message

This error was seen a lot at CCCamp2019.

Modifying the msgb was a bad idea to begin with, the approach taken in this
patch is much cleaner.

Note that apparently many phones include the IMEISV in the Cipher Mode Complete
message even though the BSSMAP Cipher Mode Command did not include the Cipher
Response Mode IE. So, even though we did not specifically ask for the Cipher
Mode Complete to include any identity, many MS default to including the IMEISV
of their own accord. Reproduce: attach to osmo-msc with ciphering enabled using
a Samsung Galaxy S4mini.

Related: OS#4168
Change-Id: Icd8dad18d6dda24d075dd8da72c3d6db1302090d
Neels Hofmeyr 3 years ago
parent eb1b03a98a
commit e9a3911844
  1. 1
  2. 12
  3. 14

@ -210,6 +210,7 @@ struct ran_msg {
* alg_id == 0 means no such IE was present. */
uint8_t alg_id;
const char *imeisv;
const struct tlv_p_entry *l3_msg;
} cipher_mode_complete;
struct {
enum gsm0808_cause bssap_cause;

@ -1407,6 +1407,18 @@ int msc_a_ran_dec_from_msc_i(struct msc_a *msc_a, struct msc_a_ran_dec_data *d)
vlr_subscr_rx_ciph_res(vsub, VLR_CIPH_COMPL);
rc = 0;
/* Evaluate enclosed L3 message, typically Identity Response (IMEISV) */
if (msg->cipher_mode_complete.l3_msg) {
unsigned char *data = (unsigned char*)(msg->cipher_mode_complete.l3_msg->val);
uint16_t len = msg->cipher_mode_complete.l3_msg->len;
struct msgb *dtap = msgb_alloc(len, "DTAP from Cipher Mode Complete");
unsigned char *pos = msgb_put(dtap, len);
memcpy(pos, data, len);
dtap->l3h = pos;
rc = msc_a_up_l3(msc_a, dtap);

@ -194,18 +194,10 @@ static int ran_a_decode_cipher_mode_complete(struct ran_dec *ran_dec, struct msg
ran_dec_msg.cipher_mode_complete.alg_id = ie_chosen_encr_alg->val[0];
rc = ran_decoded(ran_dec, &ran_dec_msg);
if (ie_l3_msg)
ran_dec_msg.cipher_mode_complete.l3_msg = ie_l3_msg;
if (ie_l3_msg) {
msg->l3h = (uint8_t*)ie_l3_msg->val;
msgb_l3trim(msg, ie_l3_msg->len);
ran_dec_msg = (struct ran_msg){
.msg_type = RAN_MSG_DTAP,
.msg_name = "BSSMAP Ciphering Mode Complete (L3 Message Contents)",
.dtap = msg,
ran_decoded(ran_dec, &ran_dec_msg);
rc = ran_decoded(ran_dec, &ran_dec_msg);
return rc;