aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Smith <osmith@sysmocom.de>2020-05-06 11:25:29 +0200
committerOliver Smith <osmith@sysmocom.de>2020-05-06 15:09:01 +0200
commitfca8a0a93593e0fe1d616a1473ad7295c7092b43 (patch)
tree10f2baac43fcb5c5d2accbb97ba2f4cb2c4489ae
parent7b4e5b1390cad9087e5d8f7b8b3344b9e2c677fa (diff)
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
-rw-r--r--include/osmocom/gsupclient/gsup_req.h4
-rw-r--r--include/osmocom/hlr/db.h1
-rw-r--r--include/osmocom/hlr/imsi_pseudo.h1
-rw-r--r--src/db.c5
-rw-r--r--src/db_imsi_pseudo.c34
-rw-r--r--src/gsup_server.c6
-rw-r--r--src/hlr.c14
7 files changed, 65 insertions, 0 deletions
diff --git a/include/osmocom/gsupclient/gsup_req.h b/include/osmocom/gsupclient/gsup_req.h
index 2d3cf38..c219d00 100644
--- a/include/osmocom/gsupclient/gsup_req.h
+++ b/include/osmocom/gsupclient/gsup_req.h
@@ -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,
diff --git a/include/osmocom/hlr/db.h b/include/osmocom/hlr/db.h
index abb7357..35357a6 100644
--- a/include/osmocom/hlr/db.h
+++ b/include/osmocom/hlr/db.h
@@ -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
};
diff --git a/include/osmocom/hlr/imsi_pseudo.h b/include/osmocom/hlr/imsi_pseudo.h
index e1118c3..329d1ba 100644
--- a/include/osmocom/hlr/imsi_pseudo.h
+++ b/include/osmocom/hlr/imsi_pseudo.h
@@ -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);
diff --git a/src/db.c b/src/db.c
index 2949d2f..7ed05fc 100644
--- a/src/db.c
+++ b/src/db.c
@@ -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)
diff --git a/src/db_imsi_pseudo.c b/src/db_imsi_pseudo.c
index d1c09ab..e6fd68f 100644
--- a/src/db_imsi_pseudo.c
+++ b/src/db_imsi_pseudo.c
@@ -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;
+}
diff --git a/src/gsup_server.c b/src/gsup_server.c
index 888507c..ca2ad5f 100644
--- a/src/gsup_server.c
+++ b/src/gsup_server.c
@@ -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",
diff --git a/src/hlr.c b/src/hlr.c
index e4d6c23..634312c 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -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 */