src/hlr.c: resolve/scramble pseudo IMSI in GSUP

Resolve the pseudonymous IMSI to the real IMSI as soon as possible, when
a GSUP message arrives. Use the real IMSI internally in OsmoHLR, so the
existing logic does not need to be changed. Scramble the IMSI back to the
pseudonymous IMSI in one common place (gsup_server_send_req_response)
right before responding to GSUP messages.

Related: OS#4476
Change-Id: I400810f96efca7746dd4ba1bed666acaea425e8a
This commit is contained in:
Oliver Smith 2020-05-06 11:25:29 +02:00
parent 7b4e5b1390
commit fca8a0a935
7 changed files with 65 additions and 0 deletions

View File

@ -80,6 +80,10 @@ struct osmo_gsup_req {
/* A decoded GSUP message still points into the received msgb. For a decoded osmo_gsup_message to remain valid,
* we also need to keep the msgb. */
struct msgb *msg;
/* The pseudonymous IMSI in gsup->imsi is replaced with the real IMSI right after receiving the message. A
* copy of the pseudonymous IMSI is stored here for the reply. */
char imsi_pseudo[OSMO_IMSI_BUF_SIZE];
};
struct osmo_gsup_req *osmo_gsup_req_new(void *ctx, const struct osmo_cni_peer_id *from_peer, struct msgb *msg,

View File

@ -37,6 +37,7 @@ enum stmt_idx {
DB_STMT_PSEUDO_INSERT,
DB_STMT_PSEUDO_DELETE,
DB_STMT_PSEUDO_NEXT,
DB_STMT_PSEUDO_RESOLVE,
_NUM_DB_STMT
};

View File

@ -17,3 +17,4 @@ int db_get_imsi_pseudo_data(struct db_context *dbc, int64_t subscr_id, struct im
int db_alloc_imsi_pseudo(struct db_context *dbc, int64_t subscr_id, const char *imsi_pseudo, int64_t imsi_pseudo_i);
int db_dealloc_imsi_pseudo(struct db_context *dbc, const char *imsi_pseudo);
int db_get_imsi_pseudo_next(struct db_context *dbc, char *imsi_pseudo);
int db_get_imsi_pseudo_resolve(struct db_context *dbc, const char *imsi_pseudo, char *imsi);

View File

@ -102,6 +102,11 @@ static const char *stmt_sql[] = {
" WHERE imsi_pseudo IS NULL"
" ORDER BY RANDOM()"
" LIMIT 1",
[DB_STMT_PSEUDO_RESOLVE] =
"SELECT imsi"
" FROM subscriber"
" LEFT JOIN subscriber_imsi_pseudo ON subscriber_id = subscriber.id"
" WHERE imsi_pseudo = $imsi_pseudo",
};
static void sql3_error_log_cb(void *arg, int err_code, const char *msg)

View File

@ -141,3 +141,37 @@ int db_get_imsi_pseudo_next(struct db_context *dbc, char *imsi_pseudo)
db_remove_reset(stmt);
return ret;
}
/*! Resolve a pseudo IMSI to the real IMSI.
* \param[in] dbc database context.
* \param[in] imsi_pseudo the IMSI to be resolved
* \param[out] imsi buffer with length GSM23003_IMSI_MAX_DIGITS+1.
* \returns 0: success, -1: no associated real IMSI, -2: SQL error. */
int db_get_imsi_pseudo_resolve(struct db_context *dbc, const char *imsi_pseudo, char *imsi)
{
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_PSEUDO_RESOLVE];
int rc, ret=0;
if (!db_bind_text(stmt, "$imsi_pseudo", imsi_pseudo))
return -EIO;
rc = sqlite3_step(stmt);
switch (rc) {
case SQLITE_ROW:
/* Can't use copy_sqlite3_text_to_buf, as it assumes the wrong size for imsi_pseudo */
osmo_strlcpy(imsi, (const char *)sqlite3_column_text(stmt, 0), GSM23003_IMSI_MAX_DIGITS + 1);
break;
case SQLITE_DONE:
LOGP(DPSEUDO, LOGL_NOTICE, "cannot resolve pseudonymous IMSI '%s': no associated real IMSI found\n",
imsi_pseudo);
ret = -1;
break;
default:
LOGP(DPSEUDO, LOGL_ERROR, "cannot resolve pseudonymous IMSI '%s': SQL error: %d\n", imsi_pseudo, rc);
ret = -2;
break;
}
db_remove_reset(stmt);
return ret;
}

View File

@ -30,6 +30,7 @@
#include <osmocom/hlr/gsup_server.h>
#include <osmocom/hlr/gsup_router.h>
#include <osmocom/hlr/logging.h>
#define LOG_GSUP_CONN(conn, level, fmt, args...) \
LOGP(DLGSUP, level, "GSUP peer %s: " fmt, \
@ -95,6 +96,11 @@ static void gsup_server_send_req_response(struct osmo_gsup_req *req, struct osmo
return;
}
if (req->imsi_pseudo[0]) {
LOGP(DPSEUDO, LOGL_DEBUG, "pseudo IMSI scramble: '%s' => '%s'\n", response->imsi, req->imsi_pseudo);
strncpy(response->imsi, req->imsi_pseudo, sizeof(response->imsi));
}
rc = osmo_gsup_encode(msg, response);
if (rc) {
LOG_GSUP_REQ(req, LOGL_ERROR, "Unable to encode: {%s}\n",

View File

@ -48,6 +48,7 @@
#include <osmocom/hlr/rand.h>
#include <osmocom/hlr/hlr_vty.h>
#include <osmocom/hlr/hlr_ussd.h>
#include <osmocom/hlr/imsi_pseudo.h>
#include <osmocom/hlr/dgsm.h>
#include <osmocom/hlr/proxy.h>
#include <osmocom/hlr/lu_fsm.h>
@ -512,6 +513,19 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
return 0;
}
/* Resolve pseudonymous IMSI */
if (g_hlr->imsi_pseudo) {
char imsi[OSMO_IMSI_BUF_SIZE];
if (db_get_imsi_pseudo_resolve(g_hlr->dbc, req->gsup.imsi, imsi) == 0) {
LOGP(DPSEUDO, LOGL_DEBUG, "pseudo IMSI resolve: '%s' => '%s'\n", req->gsup.imsi, imsi);
strncpy(req->imsi_pseudo, req->gsup.imsi, sizeof(req->imsi_pseudo));
strncpy((char *)req->gsup.imsi, imsi, sizeof(req->gsup.imsi));
} else {
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "pseudonymous IMSI unknown");
return -1;
}
}
/* HLR related messages that are handled at this HLR instance */
switch (req->gsup.message_type) {
/* requests sent to us */