mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-03 05:23:43 +00:00
gbproxy: Test and fix IMSI/TMSI matching
This adds a test for gbprox_set_patch_filter() and gbprox_check_imsi(). It also fixes the masking of the type field when IMSIs are checked by using GSM_MI_TYPE_MASK (0x07) instead of 0x0f. Sponsored-by: On-Waves ehf
This commit is contained in:
@@ -130,4 +130,6 @@ void gbprox_register_tlli(struct gbproxy_peer *peer, uint32_t tlli,
|
|||||||
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);
|
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);
|
||||||
void gbproxy_peer_free(struct gbproxy_peer *peer);
|
void gbproxy_peer_free(struct gbproxy_peer *peer);
|
||||||
|
|
||||||
|
int gbprox_check_imsi(struct gbproxy_peer *peer,
|
||||||
|
const uint8_t *imsi, size_t imsi_len);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ static int is_mi_tmsi(const uint8_t *value, size_t value_len)
|
|||||||
if (value_len != GSM48_TMSI_LEN)
|
if (value_len != GSM48_TMSI_LEN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!value || (value[0] & 0x0f) != GSM_MI_TYPE_TMSI)
|
if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_TMSI)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -366,7 +366,7 @@ static int is_mi_imsi(const uint8_t *value, size_t value_len)
|
|||||||
if (value_len == 0)
|
if (value_len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!value || (value[0] & 0x0f) != GSM_MI_TYPE_IMSI)
|
if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -507,7 +507,7 @@ int gbprox_set_patch_filter(struct gbproxy_config *cfg, const char *filter,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gbprox_check_imsi(struct gbproxy_peer *peer,
|
int gbprox_check_imsi(struct gbproxy_peer *peer,
|
||||||
const uint8_t *imsi, size_t imsi_len)
|
const uint8_t *imsi, size_t imsi_len)
|
||||||
{
|
{
|
||||||
char mi_buf[200];
|
char mi_buf[200];
|
||||||
@@ -516,8 +516,10 @@ static int gbprox_check_imsi(struct gbproxy_peer *peer,
|
|||||||
if (!peer->cfg->check_imsi)
|
if (!peer->cfg->check_imsi)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
rc = is_mi_imsi(imsi, imsi_len);
|
||||||
|
if (rc > 0)
|
||||||
rc = gsm48_mi_to_string(mi_buf, sizeof(mi_buf), imsi, imsi_len);
|
rc = gsm48_mi_to_string(mi_buf, sizeof(mi_buf), imsi, imsi_len);
|
||||||
if (rc < 1) {
|
if (rc <= 0) {
|
||||||
LOGP(DGPRS, LOGL_NOTICE, "Invalid IMSI %s\n",
|
LOGP(DGPRS, LOGL_NOTICE, "Invalid IMSI %s\n",
|
||||||
osmo_hexdump(imsi, imsi_len));
|
osmo_hexdump(imsi, imsi_len));
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -1474,6 +1474,77 @@ static void test_gbproxy_tlli_expire(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_gbproxy_imsi_matching(void)
|
||||||
|
{
|
||||||
|
struct gbproxy_config cfg = {0};
|
||||||
|
struct gbproxy_peer *peer;
|
||||||
|
const char *err_msg = NULL;
|
||||||
|
const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0xf6 };
|
||||||
|
const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
|
||||||
|
const uint8_t imsi3_bad[] = { GSM_MI_TYPE_IMSI | 0x10, 0xee, 0x54, 0xff };
|
||||||
|
const uint8_t tmsi1[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22, 0x33, 0x44 };
|
||||||
|
const uint8_t tmsi2_bad[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22 };
|
||||||
|
const uint8_t imei1[] = { GSM_MI_TYPE_IMEI | 0x10, 0x32, 0x54, 0xf6 };
|
||||||
|
const uint8_t imei2[] = { GSM_MI_TYPE_IMEI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
|
||||||
|
const char *filter_re1 = ".*";
|
||||||
|
const char *filter_re2 = "^1234";
|
||||||
|
const char *filter_re3 = "^4321";
|
||||||
|
const char *filter_re4_bad = "^12[";
|
||||||
|
|
||||||
|
printf("=== Test IMSI/TMSI matching ===\n\n");
|
||||||
|
|
||||||
|
gbproxy_init_config(&cfg);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 0);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re1, &err_msg) == 0);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 1);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 1);
|
||||||
|
|
||||||
|
err_msg = NULL;
|
||||||
|
OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re4_bad, &err_msg) == -1);
|
||||||
|
OSMO_ASSERT(err_msg != NULL);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 0);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 1);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_set_patch_filter(&cfg, NULL, &err_msg) == 0);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 0);
|
||||||
|
|
||||||
|
peer = gbproxy_peer_alloc(&cfg, 20);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 1);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 1);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 1);
|
||||||
|
/* imsi3_bad contains 0xE and 0xF digits, but the conversion function
|
||||||
|
* doesn't complain, so gbprox_check_imsi() doesn't return -1 in this
|
||||||
|
* case. */
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re3, &err_msg) == 0);
|
||||||
|
OSMO_ASSERT(cfg.check_imsi == 1);
|
||||||
|
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 0);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 0);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
|
||||||
|
OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
|
||||||
|
|
||||||
|
/* TODO: Check correct length but wrong type with is_mi_tmsi */
|
||||||
|
|
||||||
|
gbproxy_peer_free(peer);
|
||||||
|
}
|
||||||
|
|
||||||
static struct log_info_cat gprs_categories[] = {
|
static struct log_info_cat gprs_categories[] = {
|
||||||
[DGPRS] = {
|
[DGPRS] = {
|
||||||
.name = "DGPRS",
|
.name = "DGPRS",
|
||||||
@@ -1517,6 +1588,7 @@ int main(int argc, char **argv)
|
|||||||
test_tlv_shift_functions();
|
test_tlv_shift_functions();
|
||||||
test_gbproxy();
|
test_gbproxy();
|
||||||
test_gbproxy_ident_changes();
|
test_gbproxy_ident_changes();
|
||||||
|
test_gbproxy_imsi_matching();
|
||||||
test_gbproxy_ra_patching();
|
test_gbproxy_ra_patching();
|
||||||
test_gbproxy_tlli_expire();
|
test_gbproxy_tlli_expire();
|
||||||
printf("===== GbProxy test END\n\n");
|
printf("===== GbProxy test END\n\n");
|
||||||
|
|||||||
@@ -1479,6 +1479,8 @@ Peers:
|
|||||||
NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
|
NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||||
NSEI mismatch : 1
|
NSEI mismatch : 1
|
||||||
TLLI-Cache: 0
|
TLLI-Cache: 0
|
||||||
|
=== Test IMSI/TMSI matching ===
|
||||||
|
|
||||||
=== test_gbproxy_ra_patching ===
|
=== test_gbproxy_ra_patching ===
|
||||||
--- Initialise SGSN ---
|
--- Initialise SGSN ---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user