diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-09-15 05:20:40 +0800 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-09-15 18:58:36 +0800 |
commit | 3268540fc38c5181921ad427f84f36d412d061f7 (patch) | |
tree | b4bd63950bd45a8e1962ca5033bf7c2aa438a43c /openbsc/src/nat/bsc_nat_utils.c | |
parent | d880f54f4b345b18cda8bf939445d9d37304bc32 (diff) |
nat: Parse the id response, extract the IMSI, compare it
Add a test case and also add a basic check that we got some
size checks correct. The next step is to act on the result.
Diffstat (limited to 'openbsc/src/nat/bsc_nat_utils.c')
-rw-r--r-- | openbsc/src/nat/bsc_nat_utils.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c index 7387b517a..a5917371b 100644 --- a/openbsc/src/nat/bsc_nat_utils.c +++ b/openbsc/src/nat/bsc_nat_utils.c @@ -369,6 +369,35 @@ static int _cr_check_pag_resp(struct bsc_connection *bsc, uint8_t *data, unsigne return auth_imsi(bsc, mi_string); } +static int _dt_check_id_resp(struct bsc_connection *bsc, + uint8_t *data, unsigned int length, + struct sccp_connections *con) +{ + char mi_string[GSM48_MI_SIZE]; + uint8_t mi_type; + int ret; + + if (length < 2) { + LOGP(DNAT, LOGL_ERROR, "mi does not fit.\n"); + return -1; + } + + if (data[0] < length - 1) { + LOGP(DNAT, LOGL_ERROR, "mi length too big.\n"); + return -2; + } + + mi_type = data[1] & GSM_MI_TYPE_MASK; + gsm48_mi_to_string(mi_string, sizeof(mi_string), &data[1], data[0]); + + if (mi_type != GSM_MI_TYPE_IMSI) + return 0; + + ret = auth_imsi(bsc, mi_string); + con->imsi_checked = 1; + return ret; +} + /* Filter out CR data... */ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed, int *con_type) { @@ -434,10 +463,38 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg, struct sccp_connections *con, struct bsc_nat_parsed *parsed) { + uint32_t len; + struct gsm48_hdr *hdr48; + if (con->imsi_checked) return 0; - return 0; + /* only care about DTAP messages */ + if (parsed->bssap != BSSAP_MSG_DTAP) + return 0; + + /* gsm_type is actually the size of the dtap */ + len = parsed->gsm_type; + if (len < msgb_l3len(msg) - 3) { + LOGP(DNAT, LOGL_ERROR, "Not enough space for DTAP.\n"); + return -1; + } + + if (len < sizeof(*hdr48)) { + LOGP(DNAT, LOGL_ERROR, "GSM48 header does not fit.\n"); + return -1; + } + + msg->l4h = &msg->l3h[3]; + hdr48 = (struct gsm48_hdr *) msg->l4h; + + if (hdr48->proto_discr == GSM48_PDISC_MM && + (hdr48->msg_type & 0xbf) == GSM48_MT_MM_ID_RESP) { + return _dt_check_id_resp(bsc, &hdr48->data[0], len - sizeof(*hdr48), con); + } else { + printf("%d %x\n", hdr48->proto_discr, hdr48->msg_type); + return 0; + } } void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv) |