mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
synced 2025-11-02 21:23:30 +00:00
Compare commits
5 Commits
6784ed14b7
...
1.6.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6e983b985 | ||
|
|
559f4e8024 | ||
|
|
c9b80363f4 | ||
|
|
42f82975f2 | ||
|
|
4af47bb3d8 |
10
configure.ac
10
configure.ac
@@ -41,11 +41,11 @@ PKG_PROG_PKG_CONFIG([0.20])
|
||||
|
||||
PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1])
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.5.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.4.0)
|
||||
|
||||
PKG_CHECK_MODULES(SQLITE3, sqlite3)
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ BuildRequires: python3
|
||||
%if 0%{?suse_version}
|
||||
BuildRequires: systemd-rpm-macros
|
||||
%endif
|
||||
BuildRequires: pkgconfig(libosmoabis) >= 1.5.0
|
||||
BuildRequires: pkgconfig(libosmocore) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmogsm) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmoabis) >= 1.4.0
|
||||
BuildRequires: pkgconfig(libosmocore) >= 1.8.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.8.0
|
||||
BuildRequires: pkgconfig(libosmogsm) >= 1.8.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.8.0
|
||||
BuildRequires: pkgconfig(sqlite3)
|
||||
BuildRequires: pkgconfig(talloc) >= 2.0.1
|
||||
# only needed for populate_hlr_db.pl
|
||||
|
||||
33
debian/changelog
vendored
33
debian/changelog
vendored
@@ -1,36 +1,15 @@
|
||||
osmo-hlr (1.7.0) unstable; urgency=medium
|
||||
osmo-hlr (1.6.2) unstable; urgency=medium
|
||||
|
||||
[ Oliver Smith ]
|
||||
* Run struct_endianness.py
|
||||
* tests/db/db_test.err: adjust to XOR-3G rename
|
||||
* debian: set compat level to 10
|
||||
* systemd: depend on networking-online.target
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* mslookup: Call osmo_fd_unregister() before closing and changing bfd->fd
|
||||
-- Oliver Smith <osmith@sysmocom.de> Fri, 26 May 2023 14:54:12 +0200
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* tests/auc/Makefile.am: put object files to LDADD
|
||||
* tests/*/Makefile.am: move -I to AM_CPPFLAGS
|
||||
* lu_fsm: fix memleak in lu_fsm_wait_insert_data_result()
|
||||
* ussd: fix GSUP memleaks in rx_proc_ss_{req,error}()
|
||||
* gsup_server: fix msgb memleak in osmo_gsup_server_read_cb()
|
||||
* USSD: fix handling of ussd-DataCodingScheme != 0x0f
|
||||
osmo-hlr (1.6.1) unstable; urgency=medium
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* hlr: use talloc for memory allocation in osmo_gsup_create_insert_subscriber_data_msg
|
||||
* Add support for multiple APN profiles for subscriber data
|
||||
* Run struct_endianness.py
|
||||
* tests: adjust to XOR-3G rename in libosmocore
|
||||
|
||||
[ Harald Welte ]
|
||||
* Introduce support for XOR-2G algorithm
|
||||
* cosmetic: gen_ts_55_205_test_sets/func_template.c: Use tab-indent
|
||||
* cosmetic: gen_ts_55_205_test_sets/main_template tabs istead of spaces
|
||||
* Port to new libosmogsm 'struct osmo_sub_auth_data2'
|
||||
* src/db.c: Switch from "const char *statements" to "const char * const"
|
||||
* db: extend database schema to support 256bit K and/or OP[c] values
|
||||
* Add VTY support for TUAK algorithm
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 14:41:33 +0200
|
||||
-- Oliver Smith <osmith@sysmocom.de> Thu, 23 Feb 2023 10:23:04 +0100
|
||||
|
||||
osmo-hlr (1.6.0) unstable; urgency=medium
|
||||
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
10
|
||||
9
|
||||
|
||||
10
debian/control
vendored
10
debian/control
vendored
@@ -2,17 +2,17 @@ Source: osmo-hlr
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
|
||||
Build-Depends: debhelper (>= 10),
|
||||
Build-Depends: debhelper (>= 9),
|
||||
pkg-config,
|
||||
dh-autoreconf,
|
||||
autotools-dev,
|
||||
python3-minimal,
|
||||
libosmocore-dev (>= 1.9.0),
|
||||
libosmo-abis-dev (>= 1.5.0),
|
||||
libosmo-netif-dev (>= 1.4.0),
|
||||
libosmocore-dev (>= 1.8.0),
|
||||
libosmo-abis-dev (>= 1.4.0),
|
||||
libosmo-netif-dev (>= 1.3.0),
|
||||
libsqlite3-dev,
|
||||
sqlite3,
|
||||
osmo-gsm-manuals-dev (>= 1.5.0)
|
||||
osmo-gsm-manuals-dev (>= 1.4.0)
|
||||
Standards-Version: 3.9.6
|
||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
|
||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
|
||||
|
||||
@@ -24,9 +24,3 @@ hlr
|
||||
bind ip 127.0.0.1
|
||||
ussd route prefix *#100# internal own-msisdn
|
||||
ussd route prefix *#101# internal own-imsi
|
||||
ps
|
||||
pdp-profiles default
|
||||
profile 1
|
||||
apn internet
|
||||
profile 2
|
||||
apn *
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
const uint8_t *rand_auts, const uint8_t *auts);
|
||||
|
||||
@@ -40,8 +40,6 @@ enum stmt_idx {
|
||||
DB_STMT_SET_LAST_LU_SEEN,
|
||||
DB_STMT_SET_LAST_LU_SEEN_PS,
|
||||
DB_STMT_EXISTS_BY_IMSI,
|
||||
DB_STMT_EXISTS_AUTHORIZED_BY_IMSI,
|
||||
DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI,
|
||||
DB_STMT_EXISTS_BY_MSISDN,
|
||||
DB_STMT_IND_ADD,
|
||||
DB_STMT_IND_SELECT,
|
||||
@@ -72,8 +70,8 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_log
|
||||
|
||||
/* obtain the authentication data for a given imsi */
|
||||
int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
int64_t *subscr_id);
|
||||
|
||||
int db_update_sqn(struct db_context *dbc, int64_t id,
|
||||
@@ -123,7 +121,7 @@ struct hlr_subscriber {
|
||||
* See https://sqlite.org/lang_datefunc.html, function datetime(). */
|
||||
#define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
/* Like struct osmo_sub_auth_data2, but the keys are in hexdump representation.
|
||||
/* Like struct osmo_sub_auth_data, but the keys are in hexdump representation.
|
||||
* This is useful because SQLite requires them in hexdump format, and callers
|
||||
* like the VTY and CTRL interface also have them available as hexdump to begin
|
||||
* with. In the binary format, a VTY command would first need to hexparse,
|
||||
@@ -159,8 +157,6 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
|
||||
int db_subscr_update_imei_by_imsi(struct db_context *dbc, const char* imsi, const char *imei);
|
||||
|
||||
int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi);
|
||||
int db_subscr_authorized_by_imsi(struct db_context *dbc, const char *imsi);
|
||||
int db_subscr_is_created_on_demand_by_imsi(struct db_context *dbc, const char *imsi, unsigned int msisdn_len);
|
||||
int db_subscr_exists_by_msisdn(struct db_context *dbc, const char *msisdn);
|
||||
|
||||
int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *filter,
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <osmocom/gsupclient/cni_peer_id.h>
|
||||
#include <osmocom/gsupclient/gsup_req.h>
|
||||
|
||||
#define OSMO_DGSM_DEFAULT_LOCAL_ATTACH_MAX_AGE 60 * 60
|
||||
#define OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS 2000
|
||||
#define LOG_DGSM(imsi, level, fmt, args...) \
|
||||
LOGP(DDGSM, level, "(IMSI-%s) " fmt, imsi, ##args)
|
||||
|
||||
@@ -69,6 +69,8 @@ void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups);
|
||||
int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
|
||||
uint8_t *apn_buf, size_t apn_buf_size);
|
||||
int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
|
||||
enum osmo_gsup_cn_domain cn_domain, void *talloc_ctx);
|
||||
uint8_t *msisdn_enc, size_t msisdn_enc_size,
|
||||
uint8_t *apn_buf, size_t apn_buf_size,
|
||||
enum osmo_gsup_cn_domain cn_domain);
|
||||
int osmo_gsup_forward_to_local_peer(struct osmo_gsup_server *server, const struct osmo_cni_peer_id *to_peer,
|
||||
struct osmo_gsup_req *req, struct osmo_gsup_message *modified_gsup);
|
||||
|
||||
@@ -56,24 +56,8 @@ struct hlr {
|
||||
|
||||
struct llist_head euse_list;
|
||||
struct hlr_euse *euse_default;
|
||||
|
||||
struct {
|
||||
enum gsm48_gmm_cause cs;
|
||||
enum gsm48_gmm_cause ps;
|
||||
} reject_cause;
|
||||
struct {
|
||||
enum gsm48_gmm_cause cs;
|
||||
enum gsm48_gmm_cause ps;
|
||||
} no_proxy_reject_cause;
|
||||
|
||||
/* PS: APN default configuration used by Subscription Data on ISR */
|
||||
struct {
|
||||
struct {
|
||||
bool enabled;
|
||||
struct osmo_gsup_pdp_info pdp_infos[OSMO_GSUP_MAX_NUM_PDP_INFO];
|
||||
size_t num_pdp_infos;
|
||||
} pdp_profile;
|
||||
} ps;
|
||||
enum gsm48_gmm_cause reject_cause;
|
||||
enum gsm48_gmm_cause no_proxy_reject_cause;
|
||||
|
||||
/* NCSS (call independent) session guard timeout value */
|
||||
int ncss_guard_timeout;
|
||||
@@ -127,10 +111,7 @@ struct hlr {
|
||||
char *domain_suffix;
|
||||
struct osmo_mslookup_client_method *running;
|
||||
} mdns;
|
||||
bool subscr_create_on_demand_fallback;
|
||||
} client;
|
||||
bool auth_imsi_only;
|
||||
bool ignore_created_on_demand;
|
||||
} mslookup;
|
||||
};
|
||||
|
||||
@@ -140,4 +121,3 @@ struct hlr_subscriber;
|
||||
|
||||
void osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr);
|
||||
int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val, bool is_ps);
|
||||
void dgsm_fallback_to_hlr();
|
||||
|
||||
@@ -35,15 +35,11 @@ enum hlr_vty_node {
|
||||
MSLOOKUP_SERVER_NODE,
|
||||
MSLOOKUP_SERVER_MSC_NODE,
|
||||
MSLOOKUP_CLIENT_NODE,
|
||||
PS_NODE,
|
||||
PS_PDP_PROFILES_NODE,
|
||||
PS_PDP_PROFILES_PROFILE_NODE,
|
||||
};
|
||||
|
||||
|
||||
#define A38_XOR_MIN_KEY_LEN 12
|
||||
#define A38_XOR_MAX_KEY_LEN 16
|
||||
#define A38_XOR2G_KEY_LEN 16
|
||||
#define A38_COMP128_KEY_LEN 16
|
||||
#define MILENAGE_KEY_LEN 16
|
||||
|
||||
|
||||
@@ -71,8 +71,6 @@ void proxy_init(struct osmo_gsup_server *gsup_server_to_vlr);
|
||||
void proxy_del(struct proxy *proxy);
|
||||
void proxy_set_gc_period(struct proxy *proxy, uint32_t gc_period);
|
||||
|
||||
struct osmo_gsup_req *proxy_deferred_gsup_req_get_by_imsi(struct proxy *proxy, const char *imsi);
|
||||
|
||||
/* The API to access / modify proxy entries keeps the implementation opaque, to make sure that we can easily move proxy
|
||||
* storage to SQLite db. */
|
||||
int proxy_subscr_get_by_imsi(struct proxy_subscr *dst, struct proxy *proxy, const char *imsi);
|
||||
|
||||
@@ -35,7 +35,6 @@ enum osmo_mslookup_id_type {
|
||||
OSMO_MSLOOKUP_ID_NONE = 0,
|
||||
OSMO_MSLOOKUP_ID_IMSI,
|
||||
OSMO_MSLOOKUP_ID_MSISDN,
|
||||
OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED,
|
||||
};
|
||||
|
||||
extern const struct value_string osmo_mslookup_id_type_names[];
|
||||
|
||||
@@ -37,8 +37,6 @@ typedef void (*osmo_mslookup_cb_t)(struct osmo_mslookup_client *client,
|
||||
* This query handling info is not seen by the individual method implementations, to clarify that it is the
|
||||
* osmo_mslookup_client layer that takes care of these details. */
|
||||
struct osmo_mslookup_query_handling {
|
||||
bool search_all;
|
||||
|
||||
/*! Wait at least this long before returning any results.
|
||||
*
|
||||
* If nonzero, result_cb will be called as soon as this delay has elapsed, either with the so far youngest age
|
||||
|
||||
@@ -71,9 +71,9 @@ CREATE TABLE auc_2g (
|
||||
CREATE TABLE auc_3g (
|
||||
subscriber_id INTEGER PRIMARY KEY, -- subscriber.id
|
||||
algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value
|
||||
k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit)
|
||||
op VARCHAR(64), -- hex string: operator's secret key (128/256bit)
|
||||
opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit)
|
||||
k VARCHAR(32) NOT NULL, -- hex string: subscriber's secret key (128bit)
|
||||
op VARCHAR(32), -- hex string: operator's secret key (128bit)
|
||||
opc VARCHAR(32), -- hex string: derived from OP and K (128bit)
|
||||
sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage
|
||||
-- nr of index bits at lower SQN end
|
||||
ind_bitlen INTEGER NOT NULL DEFAULT 5
|
||||
@@ -91,4 +91,4 @@ CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi);
|
||||
|
||||
-- Set HLR database schema version number
|
||||
-- Note: This constant is currently duplicated in src/db.c and must be kept in sync!
|
||||
PRAGMA user_version = 7;
|
||||
PRAGMA user_version = 6;
|
||||
|
||||
@@ -111,7 +111,7 @@ BOOTSTRAP_SQL = $(top_srcdir)/sql/hlr.sql
|
||||
db_bootstrap.h: $(BOOTSTRAP_SQL) $(srcdir)/db_sql2c.sed
|
||||
echo "/* DO NOT EDIT THIS FILE. It is generated from files in osmo-hlr.git/sql/ */" > "$@"
|
||||
echo "#pragma once" >> "$@"
|
||||
echo "static const char * const stmt_bootstrap_sql[] = {" >> "$@"
|
||||
echo "static const char *stmt_bootstrap_sql[] = {" >> "$@"
|
||||
cat "$(BOOTSTRAP_SQL)" \
|
||||
| sed -f "$(srcdir)/db_sql2c.sed" \
|
||||
>> "$@"
|
||||
|
||||
21
src/auc.c
21
src/auc.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -32,8 +32,8 @@
|
||||
/* compute given number of vectors using either aud2g or aud2g or a combination
|
||||
* of both. Handles re-synchronization if rand_auts and auts are set */
|
||||
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
const uint8_t *rand_auts, const uint8_t *auts)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -93,10 +93,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
: "2G only",
|
||||
auts? ", with AUTS resync" : "");
|
||||
if (aud3g) {
|
||||
DBGP("3G: k = %s\n", hex(aud3g->u.umts.k, aud3g->u.umts.k_len));
|
||||
DBGP("3G: k = %s\n", hexb(aud3g->u.umts.k));
|
||||
DBGP("3G: %s = %s\n",
|
||||
aud3g->u.umts.opc_is_op? "OP" : "opc",
|
||||
hex(aud3g->u.umts.opc, aud3g->u.umts.opc_len));
|
||||
hexb(aud3g->u.umts.opc));
|
||||
DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n",
|
||||
aud3g->u.umts.ind, aud3g->u.umts.sqn);
|
||||
}
|
||||
@@ -115,9 +115,6 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
if (aud3g) {
|
||||
/* 3G or 3G + 2G case */
|
||||
|
||||
/* backwards-compatibiliy: We assume all RES are 8 bytes long */
|
||||
vec[i].res_len = 8;
|
||||
|
||||
/* Do AUTS only for the first vector or we would use
|
||||
* the same SQN for each following key. */
|
||||
if ((i == 0) && auts) {
|
||||
@@ -126,10 +123,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
DBGP("vector [%u]: resync: rand_auts = %s\n",
|
||||
i, hex(rand_auts, 16));
|
||||
|
||||
rc = osmo_auth_gen_vec_auts2(vec+i, aud3g, auts,
|
||||
rc = osmo_auth_gen_vec_auts(vec+i, aud3g, auts,
|
||||
rand_auts, rand);
|
||||
} else {
|
||||
rc = osmo_auth_gen_vec2(vec+i, aud3g, rand);
|
||||
rc = osmo_auth_gen_vec(vec+i, aud3g, rand);
|
||||
}
|
||||
if (rc < 0) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
|
||||
@@ -157,7 +154,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
|
||||
DBGP("vector [%u]: calculating 2G separately\n", i);
|
||||
|
||||
rc = osmo_auth_gen_vec2(&vtmp, aud2g, rand);
|
||||
rc = osmo_auth_gen_vec(&vtmp, aud2g, rand);
|
||||
if (rc < 0) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector"
|
||||
"generation: [%u]: rc = %d\n", i, rc);
|
||||
@@ -168,7 +165,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
vec[i].auth_types |= OSMO_AUTH_TYPE_GSM;
|
||||
} else {
|
||||
/* 2G only case */
|
||||
rc = osmo_auth_gen_vec2(vec+i, aud2g, rand);
|
||||
rc = osmo_auth_gen_vec(vec+i, aud2g, rand);
|
||||
if (rc < 0) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
|
||||
"generation: [%u]: rc = %d\n", i, rc);
|
||||
|
||||
42
src/ctrl.c
42
src/ctrl.c
@@ -1,6 +1,6 @@
|
||||
/* OsmoHLR Control Interface implementation */
|
||||
|
||||
/* (C) 2017-2023 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Max Suraev <msuraev@sysmocom.de>
|
||||
@@ -39,7 +39,7 @@
|
||||
#define SEL_BY_ID SEL_BY "id-"
|
||||
|
||||
extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
|
||||
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc);
|
||||
int *minlen, int *maxlen);
|
||||
|
||||
#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
|
||||
|
||||
@@ -166,7 +166,7 @@ static void print_subscr_info(struct ctrl_cmd *cmd,
|
||||
);
|
||||
}
|
||||
|
||||
static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud)
|
||||
static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
|
||||
{
|
||||
if (aud->algo == OSMO_AUTH_ALG_NONE)
|
||||
return;
|
||||
@@ -178,7 +178,7 @@ static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
|
||||
hexdump_buf(aud->u.gsm.ki));
|
||||
}
|
||||
|
||||
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud)
|
||||
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
|
||||
{
|
||||
if (aud->algo == OSMO_AUTH_ALG_NONE)
|
||||
return;
|
||||
@@ -187,7 +187,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
|
||||
"\naud3g.k\t%s"
|
||||
,
|
||||
osmo_auth_alg_name(aud->algo),
|
||||
osmo_hexdump_nospc(aud->u.umts.k, aud->u.umts.k_len));
|
||||
hexdump_buf(aud->u.umts.k));
|
||||
/* hexdump uses a static string buffer, hence only one hexdump per
|
||||
* printf(). */
|
||||
ctrl_cmd_reply_printf(cmd,
|
||||
@@ -196,7 +196,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
|
||||
"\naud3g.sqn\t%" PRIu64
|
||||
,
|
||||
aud->u.umts.opc_is_op? "op" : "opc",
|
||||
osmo_hexdump_nospc(aud->u.umts.opc, aud->u.umts.opc_len),
|
||||
hexdump_buf(aud->u.umts.opc),
|
||||
aud->u.umts.ind_bitlen,
|
||||
aud->u.umts.sqn);
|
||||
}
|
||||
@@ -291,8 +291,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_aud, "info-aud");
|
||||
static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
const char *imsi;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
int rc;
|
||||
@@ -327,8 +327,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_all, "info-all");
|
||||
static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
int rc;
|
||||
@@ -492,8 +492,8 @@ static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
|
||||
struct hlr_subscriber subscr;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g_unused;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g_unused;
|
||||
int rc;
|
||||
|
||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
||||
@@ -550,7 +550,7 @@ static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
if (strcmp(tok, "none") == 0) {
|
||||
aud2g.algo = OSMO_AUTH_ALG_NONE;
|
||||
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
|
||||
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen)) {
|
||||
cmd->reply = "Unknown auth algorithm.";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
@@ -592,8 +592,8 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
struct hlr_subscriber subscr;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
struct osmo_sub_auth_data2 aud2g_unused;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g_unused;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
int rc;
|
||||
|
||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
||||
@@ -618,9 +618,9 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
|
||||
cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo),
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, aud3g.u.umts.k_len),
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, sizeof(aud3g.u.umts.k)),
|
||||
aud3g.u.umts.opc_is_op ? "OP" : "OPC",
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, aud3g.u.umts.opc_len),
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)),
|
||||
aud3g.u.umts.ind_bitlen);
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
@@ -630,8 +630,8 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
char *tmp = NULL, *tok, *saveptr;
|
||||
int minlen = 0, minlen_opc = 0;
|
||||
int maxlen = 0, maxlen_opc = 0;
|
||||
int minlen = 0;
|
||||
int maxlen = 0;
|
||||
struct sub_auth_data_str aud3g = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.u.umts = {
|
||||
@@ -657,7 +657,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
if (strcmp(tok, "none") == 0) {
|
||||
aud3g.algo = OSMO_AUTH_ALG_NONE;
|
||||
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
|
||||
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen)) {
|
||||
cmd->reply = "Unknown auth algorithm.";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
@@ -699,7 +699,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
|
||||
aud3g.u.umts.opc = tok;
|
||||
if (!osmo_is_hexstr(aud3g.u.umts.opc, minlen_opc * 2, maxlen_opc * 2, true)) {
|
||||
if (!osmo_is_hexstr(aud3g.u.umts.opc, MILENAGE_KEY_LEN * 2, MILENAGE_KEY_LEN * 2, true)) {
|
||||
cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
|
||||
65
src/db.c
65
src/db.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "db_bootstrap.h"
|
||||
|
||||
/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
|
||||
#define CURRENT_SCHEMA_VERSION 7
|
||||
#define CURRENT_SCHEMA_VERSION 6
|
||||
|
||||
#define SEL_COLUMNS \
|
||||
"id," \
|
||||
@@ -53,7 +53,7 @@
|
||||
static const char *stmt_sql[] = {
|
||||
[DB_STMT_SEL_ALL] = "SELECT " SEL_COLUMNS " FROM subscriber;",
|
||||
[DB_STMT_SEL_ALL_ORDER_LAST_SEEN] = "SELECT " SEL_COLUMNS " FROM subscriber "
|
||||
"WHERE last_lu_seen IS NOT NULL AND last_lu_seen > datetime('now','-1 month') ORDER BY last_lu_seen;",
|
||||
"WHERE last_lu_seen IS NOT NULL ORDER BY last_lu_seen;",
|
||||
[DB_STMT_SEL_FILTER_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn LIKE $search ORDER BY msisdn",
|
||||
[DB_STMT_SEL_FILTER_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi LIKE $search ORDER BY imsi",
|
||||
[DB_STMT_SEL_FILTER_IMEI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imei LIKE $search ORDER BY imei",
|
||||
@@ -92,10 +92,6 @@ static const char *stmt_sql[] = {
|
||||
[DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
|
||||
[DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
|
||||
[DB_STMT_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi",
|
||||
[DB_STMT_EXISTS_AUTHORIZED_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi AND (nam_cs = 1 OR nam_ps = 1)",
|
||||
[DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI] =
|
||||
"SELECT 1 FROM subscriber WHERE imsi = $imsi AND length(msisdn) = $msisdn_len"
|
||||
" AND nam_cs = 0 AND nam_ps = 0 AND vlr_number IS NULL",
|
||||
[DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn",
|
||||
[DB_STMT_IND_ADD] = "INSERT INTO ind (vlr) VALUES ($vlr)",
|
||||
[DB_STMT_IND_SELECT] = "SELECT ind FROM ind WHERE vlr = $vlr",
|
||||
@@ -239,7 +235,7 @@ void db_close(struct db_context *dbc)
|
||||
talloc_free(dbc);
|
||||
}
|
||||
|
||||
static int db_run_statements(struct db_context *dbc, const char * const *statements, size_t statements_count)
|
||||
static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count)
|
||||
{
|
||||
int rc = 0;
|
||||
int i;
|
||||
@@ -312,7 +308,7 @@ static int
|
||||
db_upgrade_v1(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char * const statements[] = {
|
||||
const char *statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL",
|
||||
"PRAGMA user_version = 1",
|
||||
};
|
||||
@@ -328,7 +324,7 @@ db_upgrade_v1(struct db_context *dbc)
|
||||
static int db_upgrade_v2(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char * const statements[] = {
|
||||
const char *statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14)",
|
||||
"PRAGMA user_version = 2",
|
||||
};
|
||||
@@ -441,7 +437,7 @@ static int db_upgrade_v3(struct db_context *dbc)
|
||||
"ms_purged_ps," \
|
||||
"last_lu_seen"
|
||||
|
||||
const char * const statements[] = {
|
||||
const char *statements[] = {
|
||||
"BEGIN TRANSACTION",
|
||||
"CREATE TEMPORARY TABLE subscriber_backup" SUBSCR_V3_CREATE,
|
||||
"INSERT INTO subscriber_backup SELECT " SUBSCR_V2_COLUMN_NAMES " FROM subscriber",
|
||||
@@ -464,7 +460,7 @@ static int db_upgrade_v3(struct db_context *dbc)
|
||||
static int db_upgrade_v4(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char * const statements[] = {
|
||||
const char *statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL",
|
||||
"PRAGMA user_version = 4",
|
||||
};
|
||||
@@ -480,7 +476,7 @@ static int db_upgrade_v4(struct db_context *dbc)
|
||||
static int db_upgrade_v5(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char * const statements[] = {
|
||||
const char *statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN vlr_via_proxy VARCHAR",
|
||||
"ALTER TABLE subscriber ADD COLUMN sgsn_via_proxy VARCHAR",
|
||||
"PRAGMA user_version = 5",
|
||||
@@ -497,7 +493,7 @@ static int db_upgrade_v5(struct db_context *dbc)
|
||||
static int db_upgrade_v6(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char * const statements[] = {
|
||||
const char *statements[] = {
|
||||
"CREATE TABLE ind (\n"
|
||||
" -- 3G auth IND pool to be used for this VLR\n"
|
||||
" ind INTEGER PRIMARY KEY,\n"
|
||||
@@ -517,46 +513,6 @@ static int db_upgrade_v6(struct db_context *dbc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int db_upgrade_v7(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
/* SQLite doesn't allow us to change the column type in-place, so we
|
||||
* first rename the old table, create a new table and then copy
|
||||
* the data over before deleting the old table */
|
||||
#define CREATE_AUC_3G_V7 \
|
||||
"CREATE TABLE auc_3g (\n" \
|
||||
" subscriber_id INTEGER PRIMARY KEY, -- subscriber.id\n" \
|
||||
" algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value\n" \
|
||||
" k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit)\n" \
|
||||
" op VARCHAR(64), -- hex string: operator's secret key (128/256bit)\n" \
|
||||
" opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit)\n" \
|
||||
" sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage\n" \
|
||||
" -- nr of index bits at lower SQN end\n" \
|
||||
" ind_bitlen INTEGER NOT NULL DEFAULT 5\n" \
|
||||
");"
|
||||
const char * const statements[] = {
|
||||
"BEGIN TRANSACTION",
|
||||
/* rename old table */
|
||||
"ALTER TABLE auc_3g RENAME TO old_auc_3g",
|
||||
/* create new table */
|
||||
CREATE_AUC_3G_V7,
|
||||
/* copy over old data */
|
||||
"INSERT INTO auc_3g SELECT subscriber_id, algo_id_3g, k, op, opc,sqn, ind_bitlen FROM old_auc_3g",
|
||||
/* delete old table */
|
||||
"DROP TABLE old_auc_3g",
|
||||
/* update user_version */
|
||||
"PRAGMA user_version = 7",
|
||||
"COMMIT",
|
||||
};
|
||||
|
||||
rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
|
||||
if (rc != SQLITE_DONE) {
|
||||
LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 7\n");
|
||||
return rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
typedef int (*db_upgrade_func_t)(struct db_context *dbc);
|
||||
static db_upgrade_func_t db_upgrade_path[] = {
|
||||
db_upgrade_v1,
|
||||
@@ -565,7 +521,6 @@ static db_upgrade_func_t db_upgrade_path[] = {
|
||||
db_upgrade_v4,
|
||||
db_upgrade_v5,
|
||||
db_upgrade_v6,
|
||||
db_upgrade_v7,
|
||||
};
|
||||
|
||||
static int db_get_user_version(struct db_context *dbc)
|
||||
|
||||
45
src/db_auc.c
45
src/db_auc.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -74,9 +74,9 @@ out:
|
||||
}
|
||||
|
||||
/* hexparse a specific column of a sqlite prepared statement into dst (with length check)
|
||||
* returns byte length in case of success, -EIO on error */
|
||||
static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, sqlite3_stmt *stmt,
|
||||
int col, const char *col_name, const char *imsi)
|
||||
* returns 0 for success, -EIO on error */
|
||||
static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int col, const char *col_name,
|
||||
const char *imsi)
|
||||
{
|
||||
const uint8_t *text;
|
||||
size_t col_len;
|
||||
@@ -84,15 +84,9 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, s
|
||||
/* Bytes are stored as hex strings in database, hence divide length by two */
|
||||
col_len = sqlite3_column_bytes(stmt, col) / 2;
|
||||
|
||||
if (col_len < dst_len_min) {
|
||||
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected min length %lu but has length %lu\n", col_name,
|
||||
dst_len_min, col_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (col_len > dst_len_max) {
|
||||
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected max length %lu but has length %lu\n", col_name,
|
||||
dst_len_max, col_len);
|
||||
if (col_len != dst_len) {
|
||||
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected length %lu but has length %lu\n", col_name,
|
||||
dst_len, col_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -102,10 +96,10 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, s
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (osmo_hexparse((void *)text, dst, dst_len_max) != col_len)
|
||||
if (osmo_hexparse((void *)text, dst, dst_len) != col_len)
|
||||
return -EINVAL;
|
||||
|
||||
return col_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* obtain the authentication data for a given imsi
|
||||
@@ -113,8 +107,8 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, s
|
||||
* -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data,
|
||||
* -EIO on db failure */
|
||||
int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
int64_t *subscr_id)
|
||||
{
|
||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI];
|
||||
@@ -148,8 +142,7 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
/* obtain result values using sqlite3_column_*() */
|
||||
if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
|
||||
/* we do have some 2G authentication data */
|
||||
if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), sizeof(aud2g->u.gsm.ki),
|
||||
stmt, 2, "Ki", imsi) < 0)
|
||||
if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), stmt, 2, "Ki", imsi))
|
||||
goto end_2g;
|
||||
aud2g->algo = sqlite3_column_int(stmt, 1);
|
||||
aud2g->type = OSMO_AUTH_TYPE_GSM;
|
||||
@@ -158,30 +151,24 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
end_2g:
|
||||
if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
|
||||
/* we do have some 3G authentication data */
|
||||
rc = hexparse_stmt(aud3g->u.umts.k, 16, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi);
|
||||
if (rc < 0) {
|
||||
if (hexparse_stmt(aud3g->u.umts.k, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
aud3g->u.umts.k_len = rc;
|
||||
aud3g->algo = sqlite3_column_int(stmt, 3);
|
||||
|
||||
/* UMTS Subscribers can have either OP or OPC */
|
||||
if (sqlite3_column_text(stmt, 5)) {
|
||||
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi);
|
||||
if (rc < 0) {
|
||||
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
aud3g->u.umts.opc_len = rc;
|
||||
aud3g->u.umts.opc_is_op = 1;
|
||||
} else {
|
||||
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi);
|
||||
if (rc < 0) {
|
||||
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
aud3g->u.umts.opc_len = rc;
|
||||
aud3g->u.umts.opc_is_op = 0;
|
||||
}
|
||||
aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
|
||||
@@ -207,7 +194,7 @@ int db_get_auc(struct db_context *dbc, const char *imsi,
|
||||
unsigned int num_vec, const uint8_t *rand_auts,
|
||||
const uint8_t *auts, bool separation_bit)
|
||||
{
|
||||
struct osmo_sub_auth_data2 aud2g, aud3g;
|
||||
struct osmo_sub_auth_data aud2g, aud3g;
|
||||
int64_t subscr_id;
|
||||
int ret = 0;
|
||||
int rc;
|
||||
|
||||
70
src/db_hlr.c
70
src/db_hlr.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -238,9 +238,8 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
|
||||
case OSMO_AUTH_ALG_COMP128v1:
|
||||
case OSMO_AUTH_ALG_COMP128v2:
|
||||
case OSMO_AUTH_ALG_COMP128v3:
|
||||
case OSMO_AUTH_ALG_XOR_2G:
|
||||
case OSMO_AUTH_ALG_XOR:
|
||||
break;
|
||||
case OSMO_AUTH_ALG_XOR_3G:
|
||||
case OSMO_AUTH_ALG_MILENAGE:
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" auth algo not suited for 2G: %s\n",
|
||||
@@ -268,12 +267,11 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
|
||||
switch (aud->algo) {
|
||||
case OSMO_AUTH_ALG_NONE:
|
||||
case OSMO_AUTH_ALG_MILENAGE:
|
||||
case OSMO_AUTH_ALG_XOR_3G:
|
||||
case OSMO_AUTH_ALG_XOR:
|
||||
break;
|
||||
case OSMO_AUTH_ALG_COMP128v1:
|
||||
case OSMO_AUTH_ALG_COMP128v2:
|
||||
case OSMO_AUTH_ALG_COMP128v3:
|
||||
case OSMO_AUTH_ALG_XOR_2G:
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" auth algo not suited for 3G: %s\n",
|
||||
osmo_auth_alg_name(aud->algo));
|
||||
@@ -286,12 +284,12 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
|
||||
|
||||
if (aud->algo == OSMO_AUTH_ALG_NONE)
|
||||
break;
|
||||
if (!osmo_is_hexstr(aud->u.umts.k, 32, 64, true)) {
|
||||
if (!osmo_is_hexstr(aud->u.umts.k, 32, 32, true)) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" Invalid K: '%s'\n", aud->u.umts.k);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!osmo_is_hexstr(aud->u.umts.opc, 32, 64, true)) {
|
||||
if (!osmo_is_hexstr(aud->u.umts.opc, 32, 32, true)) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" Invalid OP/OPC: '%s'\n", aud->u.umts.opc);
|
||||
return -EINVAL;
|
||||
@@ -555,59 +553,6 @@ int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*! Check if a subscriber exists and has CS or PS service in the HLR database.
|
||||
* \param[in, out] dbc database context.
|
||||
* \param[in] imsi ASCII string of IMSI digits.
|
||||
* \returns 0 if exists & authorized, -ENOENT if not, -EIO on database error.
|
||||
*/
|
||||
int db_subscr_authorized_by_imsi(struct db_context *dbc, const char *imsi) {
|
||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_EXISTS_AUTHORIZED_BY_IMSI];
|
||||
const char *err;
|
||||
int rc;
|
||||
|
||||
if (!db_bind_text(stmt, NULL, imsi))
|
||||
return -EIO;
|
||||
|
||||
rc = sqlite3_step(stmt);
|
||||
db_remove_reset(stmt);
|
||||
if (rc == SQLITE_ROW)
|
||||
return 0; /* exists */
|
||||
if (rc == SQLITE_DONE)
|
||||
return -ENOENT; /* does not exist */
|
||||
|
||||
err = sqlite3_errmsg(dbc->db);
|
||||
LOGP(DAUC, LOGL_ERROR, "Failed to check for authorized subscriber by IMSI='%s': %s\n", imsi, err);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*! Check if a subscriber exists and has ever been attached
|
||||
* \param[in, out] dbc database context.
|
||||
* \param[in] imsi ASCII string of IMSI digits.
|
||||
* \returns 0 if has vlr_number, -ENOENT if not, -EIO on database error.
|
||||
*/
|
||||
int db_subscr_is_created_on_demand_by_imsi(struct db_context *dbc, const char *imsi, unsigned int msisdn_len) {
|
||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI];
|
||||
const char *err;
|
||||
int rc;
|
||||
|
||||
if (!db_bind_text(stmt, "$imsi", imsi))
|
||||
return -EIO;
|
||||
|
||||
if (!db_bind_int(stmt, "$msisdn_len", msisdn_len))
|
||||
return -EIO;
|
||||
|
||||
rc = sqlite3_step(stmt);
|
||||
db_remove_reset(stmt);
|
||||
if (rc == SQLITE_ROW)
|
||||
return 0; /* exists */
|
||||
if (rc == SQLITE_DONE)
|
||||
return -ENOENT; /* does not exist */
|
||||
|
||||
err = sqlite3_errmsg(dbc->db);
|
||||
LOGP(DAUC, LOGL_ERROR, "Failed to check for on demand subscriber by IMSI='%s': %s\n", imsi, err);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*! Retrieve subscriber data from the HLR database.
|
||||
* \param[in,out] dbc database context.
|
||||
* \param[in] imsi ASCII string of IMSI digits.
|
||||
@@ -753,12 +698,9 @@ int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *
|
||||
copy_sqlite3_text_to_buf(subscr.imei, stmt, 3);
|
||||
subscr.nam_cs = sqlite3_column_int(stmt, 9);
|
||||
subscr.nam_ps = sqlite3_column_int(stmt, 10);
|
||||
if (show_ls) {
|
||||
if (show_ls)
|
||||
parse_last_lu_seen(&subscr.last_lu_seen, (const char *)sqlite3_column_text(stmt, 14),
|
||||
subscr.imsi, "CS");
|
||||
copy_sqlite3_text_to_buf(subscr.vlr_number, stmt, 4);
|
||||
}
|
||||
|
||||
get_cb(&subscr, data);
|
||||
rc = sqlite3_step(stmt);
|
||||
(*count)++;
|
||||
|
||||
21
src/dgsm.c
21
src/dgsm.c
@@ -58,12 +58,6 @@ static void resolve_hlr_result_cb(struct osmo_mslookup_client *client,
|
||||
if (result->rc != OSMO_MSLOOKUP_RC_RESULT) {
|
||||
LOG_DGSM(query->id.imsi, LOGL_ERROR, "Failed to resolve remote HLR: %s\n",
|
||||
osmo_mslookup_result_name_c(OTC_SELECT, query, result));
|
||||
if (g_hlr->mslookup.client.subscr_create_on_demand_fallback &&
|
||||
db_subscr_exists_by_imsi(g_hlr->dbc, query->id.imsi) != 0) {
|
||||
struct osmo_gsup_req *req = proxy_deferred_gsup_req_get_by_imsi(proxy, query->id.imsi);
|
||||
if (req && req->gsup.message_type == OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST)
|
||||
dgsm_fallback_to_hlr(req);
|
||||
}
|
||||
proxy_subscr_del(proxy, query->id.imsi);
|
||||
return;
|
||||
}
|
||||
@@ -97,17 +91,8 @@ bool dgsm_check_forward_gsup_msg(struct osmo_gsup_req *req)
|
||||
struct osmo_mslookup_query_handling handling;
|
||||
uint32_t request_handle;
|
||||
|
||||
/* If the IMSI is authorized in the local HLR, then we won't proxy */
|
||||
if (db_subscr_authorized_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0)
|
||||
return false;
|
||||
/* unless configuration tells us to do otherwise. */
|
||||
if (!g_hlr->mslookup.ignore_created_on_demand && !g_hlr->mslookup.auth_imsi_only &&
|
||||
db_subscr_exists_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0)
|
||||
return false;
|
||||
|
||||
if (!g_hlr->mslookup.auth_imsi_only && !(g_hlr->mslookup.ignore_created_on_demand &&
|
||||
db_subscr_is_created_on_demand_by_imsi(g_hlr->dbc, req->gsup.imsi,
|
||||
g_hlr->subscr_create_on_demand_rand_msisdn_len) == 0))
|
||||
/* If the IMSI is known in the local HLR, then we won't proxy. */
|
||||
if (db_subscr_exists_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0)
|
||||
return false;
|
||||
|
||||
/* Are we already forwarding this IMSI to a remote HLR? */
|
||||
@@ -183,7 +168,7 @@ void dgsm_init(void *ctx)
|
||||
dgsm_ctx = talloc_named_const(ctx, 0, "dgsm");
|
||||
INIT_LLIST_HEAD(&g_hlr->mslookup.server.local_site_services);
|
||||
|
||||
g_hlr->mslookup.server.local_attach_max_age = OSMO_DGSM_DEFAULT_LOCAL_ATTACH_MAX_AGE;
|
||||
g_hlr->mslookup.server.local_attach_max_age = 60 * 60;
|
||||
|
||||
g_hlr->mslookup.client.result_timeout_milliseconds = OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS;
|
||||
|
||||
|
||||
181
src/dgsm_vty.c
181
src/dgsm_vty.c
@@ -22,11 +22,9 @@
|
||||
#include <osmocom/mslookup/mslookup_client_mdns.h>
|
||||
#include <osmocom/mslookup/mdns.h>
|
||||
#include <osmocom/hlr/hlr_vty.h>
|
||||
#include <osmocom/hlr/proxy.h>
|
||||
#include <osmocom/hlr/mslookup_server.h>
|
||||
#include <osmocom/hlr/mslookup_server_mdns.h>
|
||||
#include <osmocom/gsupclient/cni_peer_id.h>
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
|
||||
struct cmd_node mslookup_node = {
|
||||
MSLOOKUP_NODE,
|
||||
@@ -190,53 +188,6 @@ DEFUN(cfg_mslookup_server_no_mdns_bind,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_server_max_age,
|
||||
cfg_mslookup_server_max_age_cmd,
|
||||
"max-age <1-21600>",
|
||||
"How old can the Last Location Update be for the mslookup server to respond\n"
|
||||
"max age in seconds\n")
|
||||
{
|
||||
uint32_t val = atol(argv[0]);
|
||||
g_hlr->mslookup.server.local_attach_max_age = val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_auth_imsi_only,
|
||||
cfg_mslookup_auth_imsi_only_cmd,
|
||||
"authorized-imsi-only",
|
||||
"On local GSUP, use mslookup ignoring local HLR + don't answer queries for IMSIs without PS or CS network access mode")
|
||||
{
|
||||
g_hlr->mslookup.auth_imsi_only = true;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_no_auth_imsi_only,
|
||||
cfg_mslookup_no_auth_imsi_only_cmd,
|
||||
"no authorized-imsi-only",
|
||||
NO_STR "Answer Local GSUP/mDNS queries for any IMSI in the local HLR database")
|
||||
{
|
||||
g_hlr->mslookup.auth_imsi_only = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_cod,
|
||||
cfg_mslookup_cod_cmd,
|
||||
"ignore-created-on-demand",
|
||||
"Ignore IMSIs that were created-on-demand")
|
||||
{
|
||||
g_hlr->mslookup.ignore_created_on_demand = true;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_no_cod,
|
||||
cfg_mslookup_no_cod_cmd,
|
||||
"no ignore-created-on-demand",
|
||||
NO_STR "Answer mslookup and local GSUP for created on demand IMSIs")
|
||||
{
|
||||
g_hlr->mslookup.ignore_created_on_demand = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_node mslookup_server_msc_node = {
|
||||
MSLOOKUP_SERVER_MSC_NODE,
|
||||
"%s(config-mslookup-server-msc)# ",
|
||||
@@ -399,24 +350,6 @@ DEFUN(cfg_mslookup_no_client,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_client_subscr_cod_fallback,
|
||||
cfg_mslookup_client_subscr_cod_fallback_cmd,
|
||||
"create-on-demand-fallback",
|
||||
"If the msclient does not get a response from mDNS, proceed according to this HLR subscriber-create-on-demand config")
|
||||
{
|
||||
g_hlr->mslookup.client.subscr_create_on_demand_fallback = true;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_client_no_subscr_cod_fallback,
|
||||
cfg_mslookup_client_no_subscr_cod_fallback_cmd,
|
||||
"no create-on-demand-fallback",
|
||||
NO_STR "Return IMSI UNKNOWN if the mslookup client does not receive a response from mDNS")
|
||||
{
|
||||
g_hlr->mslookup.client.subscr_create_on_demand_fallback = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mslookup_client_timeout,
|
||||
cfg_mslookup_client_timeout_cmd,
|
||||
"timeout <1-100000>",
|
||||
@@ -488,11 +421,6 @@ int config_write_mslookup(struct vty *vty)
|
||||
|
||||
vty_out(vty, "mslookup%s", VTY_NEWLINE);
|
||||
|
||||
if (g_hlr->mslookup.auth_imsi_only)
|
||||
vty_out(vty, " authorized-imsi-only%s", VTY_NEWLINE);
|
||||
if (g_hlr->mslookup.ignore_created_on_demand)
|
||||
vty_out(vty, " ignore-created-on-demand%s", VTY_NEWLINE);
|
||||
|
||||
if (g_hlr->mslookup.server.enable || !llist_empty(&g_hlr->mslookup.server.local_site_services)) {
|
||||
struct mslookup_server_msc_cfg *msc;
|
||||
|
||||
@@ -522,9 +450,6 @@ int config_write_mslookup(struct vty *vty)
|
||||
vty_out(vty, " msc ipa-name %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
|
||||
config_write_msc_services(vty, " ", msc);
|
||||
}
|
||||
if (g_hlr->mslookup.server.local_attach_max_age != OSMO_DGSM_DEFAULT_LOCAL_ATTACH_MAX_AGE)
|
||||
vty_out(vty, " max-age %u%s",
|
||||
g_hlr->mslookup.server.local_attach_max_age, VTY_NEWLINE);
|
||||
|
||||
/* If the server is disabled, still output the above to not lose the service config. */
|
||||
if (!g_hlr->mslookup.server.enable)
|
||||
@@ -554,8 +479,6 @@ int config_write_mslookup(struct vty *vty)
|
||||
vty_out(vty, " timeout %u%s",
|
||||
g_hlr->mslookup.client.result_timeout_milliseconds,
|
||||
VTY_NEWLINE);
|
||||
if (g_hlr->mslookup.client.subscr_create_on_demand_fallback)
|
||||
vty_out(vty, " create-on-demand-fallback%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@@ -622,110 +545,11 @@ DEFUN(do_mslookup_show_services,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct proxy_subscr_listentry {
|
||||
struct llist_head entry;
|
||||
timestamp_t last_update;
|
||||
struct proxy_subscr data;
|
||||
};
|
||||
|
||||
struct proxy_pending_gsup_req {
|
||||
struct llist_head entry;
|
||||
struct osmo_gsup_req *req;
|
||||
timestamp_t received_at;
|
||||
};
|
||||
|
||||
static void write_one_proxy(struct vty *vty, struct proxy_subscr_listentry *e)
|
||||
{
|
||||
struct proxy_subscr p = e->data;
|
||||
uint32_t age;
|
||||
|
||||
vty_out(vty, "%-12s %-16s %-12s:%-4u ",
|
||||
strlen(p.msisdn) == 0 ? "Unknown" : p.msisdn,
|
||||
strlen(p.imsi) == 0 ? "Unknown" : p.imsi,
|
||||
p.remote_hlr_addr.ip ? p.remote_hlr_addr.ip : "Unknown",
|
||||
p.remote_hlr_addr.port);
|
||||
|
||||
if (!timestamp_age(&e->last_update, &age)) {
|
||||
vty_out(vty, "Invalid%s", VTY_NEWLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
#define UNIT_AGO(UNITNAME, UNITVAL) \
|
||||
if (age >= (UNITVAL)) { \
|
||||
vty_out(vty, "%u%s", age / (UNITVAL), UNITNAME); \
|
||||
age = age % (UNITVAL); \
|
||||
}
|
||||
UNIT_AGO("d", 60*60*24);
|
||||
UNIT_AGO("h", 60*60);
|
||||
UNIT_AGO("m", 60);
|
||||
UNIT_AGO("s", 1);
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
#undef UNIT_AGO
|
||||
}
|
||||
|
||||
static void write_one_proxy_request(struct vty *vty, struct osmo_gsup_req *r)
|
||||
{
|
||||
vty_out(vty, "IMSI: %s TYPE: %s%s",
|
||||
r->gsup.imsi,
|
||||
osmo_gsup_message_type_name(r->gsup.message_type),
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
DEFUN(do_proxy_del_sub,
|
||||
do_proxy_del_sub_cmd,
|
||||
"proxy subscriber-delete [IMSI]",
|
||||
"Subscriber Proxy \n"
|
||||
"Delete by IMSI\n"
|
||||
"IMSI of subscriber to delete from the Proxy"
|
||||
)
|
||||
{
|
||||
const char *imsi = argv[0];
|
||||
if (!osmo_imsi_str_valid(imsi)) {
|
||||
vty_out(vty, "%% Not a valid IMSI: %s%s", imsi, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (proxy_subscr_del(g_hlr->gs->proxy, imsi) == 0)
|
||||
return CMD_SUCCESS;
|
||||
vty_out(vty, "%% Unable to delete a Proxy for: %s%s", imsi, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
DEFUN(do_proxy_show,
|
||||
do_proxy_show_cmd,
|
||||
"show proxy",
|
||||
SHOW_STR "Proxy Entries\n")
|
||||
{
|
||||
struct proxy_subscr_listentry *e;
|
||||
struct proxy_pending_gsup_req *p;
|
||||
unsigned int count = 0;
|
||||
|
||||
vty_out(vty, "MSISDN IMSI HLR AGE%s", VTY_NEWLINE);
|
||||
vty_out(vty, "------------ ---------------- -------------------- ------%s", VTY_NEWLINE);
|
||||
llist_for_each_entry(e, &g_hlr->gs->proxy->subscr_list, entry) {
|
||||
count++;
|
||||
write_one_proxy(vty, e);
|
||||
}
|
||||
|
||||
vty_out(vty, "%s%s",
|
||||
(count == 0) ? "% No proxy subscribers" : "", VTY_NEWLINE);
|
||||
if (!llist_count(&g_hlr->gs->proxy->pending_gsup_reqs))
|
||||
return CMD_SUCCESS;
|
||||
vty_out(vty, "In-flight Proxy Subscribers Requests:%s", VTY_NEWLINE);
|
||||
llist_for_each_entry(p, &g_hlr->gs->proxy->pending_gsup_reqs, entry) {
|
||||
write_one_proxy_request(vty, p->req);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void dgsm_vty_init(void)
|
||||
{
|
||||
install_element(CONFIG_NODE, &cfg_mslookup_cmd);
|
||||
|
||||
install_node(&mslookup_node, config_write_mslookup);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_auth_imsi_only_cmd);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_auth_imsi_only_cmd);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_cod_cmd);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_cod_cmd);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_cmd);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_domain_suffix_cmd);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_mdns_cmd);
|
||||
@@ -739,7 +563,6 @@ void dgsm_vty_init(void)
|
||||
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_service_cmd);
|
||||
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_cmd);
|
||||
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_addr_cmd);
|
||||
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_max_age_cmd);
|
||||
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_cmd);
|
||||
|
||||
install_node(&mslookup_server_msc_node, NULL);
|
||||
@@ -750,8 +573,6 @@ void dgsm_vty_init(void)
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_client_cmd);
|
||||
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_client_cmd);
|
||||
install_node(&mslookup_client_node, NULL);
|
||||
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_subscr_cod_fallback_cmd);
|
||||
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_no_subscr_cod_fallback_cmd);
|
||||
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_timeout_cmd);
|
||||
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_mdns_bind_cmd);
|
||||
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_mdns_domain_suffix_cmd);
|
||||
@@ -760,6 +581,4 @@ void dgsm_vty_init(void)
|
||||
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_no_gateway_proxy_cmd);
|
||||
|
||||
install_element_ve(&do_mslookup_show_services_cmd);
|
||||
install_element_ve(&do_proxy_show_cmd);
|
||||
install_element_ve(&do_proxy_del_sub_cmd);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <osmocom/hlr/gsup_server.h>
|
||||
#include <osmocom/hlr/gsup_router.h>
|
||||
#include <osmocom/hlr/hlr.h>
|
||||
|
||||
#define LOG_GSUP_CONN(conn, level, fmt, args...) \
|
||||
LOGP(DLGSUP, level, "GSUP peer %s: " fmt, \
|
||||
@@ -180,9 +179,11 @@ static int osmo_gsup_server_read_cb(struct ipa_server_conn *conn,
|
||||
|
||||
if (hh->proto == IPAC_PROTO_IPACCESS) {
|
||||
rc = ipa_server_conn_ccm(conn, msg);
|
||||
msgb_free(msg);
|
||||
if (rc < 0) /* conn is already invalid here! */
|
||||
if (rc < 0) {
|
||||
/* conn is already invalid here! */
|
||||
return -1;
|
||||
}
|
||||
msgb_free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -445,16 +446,19 @@ int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
|
||||
* \param[out] gsup The gsup message to populate.
|
||||
* \param[in] imsi The subscriber's IMSI.
|
||||
* \param[in] msisdn The subscriber's MSISDN.
|
||||
* \param[out] msisdn_enc A buffer large enough to store the MSISDN in encoded form.
|
||||
* \param[in] msisdn_enc_size Size of the buffer (must be >= OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN).
|
||||
* \param[out] apn_buf A buffer large enough to store an APN (required if cn_domain is OSMO_GSUP_CN_DOMAIN_PS).
|
||||
* \param[in] apn_buf_size Size of APN buffer (must be >= APN_MAXLEN).
|
||||
* \param[in] cn_domain The CN Domain of the subscriber connection.
|
||||
* \param[in] talloc_ctx To allocation memory for dynamic fields (msisdn, apn) in the gsup field
|
||||
* \returns 0 on success, and negative on error.
|
||||
*/
|
||||
int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
|
||||
enum osmo_gsup_cn_domain cn_domain,
|
||||
void *talloc_ctx)
|
||||
uint8_t *msisdn_enc, size_t msisdn_enc_size,
|
||||
uint8_t *apn_buf, size_t apn_buf_size,
|
||||
enum osmo_gsup_cn_domain cn_domain)
|
||||
{
|
||||
int len;
|
||||
uint8_t *msisdn_buf = talloc_size(talloc_ctx, OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN);
|
||||
|
||||
OSMO_ASSERT(gsup);
|
||||
*gsup = (struct osmo_gsup_message){
|
||||
@@ -463,29 +467,27 @@ int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup,
|
||||
|
||||
osmo_strlcpy(gsup->imsi, imsi, sizeof(gsup->imsi));
|
||||
|
||||
len = gsm48_encode_bcd_number(msisdn_buf, OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN, 0, msisdn);
|
||||
if (msisdn_enc_size < OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN)
|
||||
return -ENOSPC;
|
||||
|
||||
OSMO_ASSERT(msisdn_enc);
|
||||
len = gsm48_encode_bcd_number(msisdn_enc, msisdn_enc_size, 0, msisdn);
|
||||
if (len < 1) {
|
||||
LOGP(DLGSUP, LOGL_ERROR, "%s: Error: cannot encode MSISDN '%s'\n", imsi, msisdn);
|
||||
return -ENOSPC;
|
||||
}
|
||||
gsup->msisdn_enc = msisdn_buf;
|
||||
gsup->msisdn_enc = msisdn_enc;
|
||||
gsup->msisdn_enc_len = len;
|
||||
|
||||
#pragma message "FIXME: deal with encoding the following data: gsup.hlr_enc"
|
||||
|
||||
gsup->cn_domain = cn_domain;
|
||||
if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS) {
|
||||
if (g_hlr->ps.pdp_profile.enabled) {
|
||||
OSMO_ASSERT(g_hlr->ps.pdp_profile.num_pdp_infos <= ARRAY_SIZE(g_hlr->ps.pdp_profile.pdp_infos));
|
||||
OSMO_ASSERT(g_hlr->ps.pdp_profile.num_pdp_infos <= ARRAY_SIZE(gsup->pdp_infos));
|
||||
memcpy(gsup->pdp_infos,
|
||||
g_hlr->ps.pdp_profile.pdp_infos,
|
||||
sizeof(struct osmo_gsup_pdp_info) * g_hlr->ps.pdp_profile.num_pdp_infos);
|
||||
gsup->num_pdp_infos = g_hlr->ps.pdp_profile.num_pdp_infos;
|
||||
} else {
|
||||
uint8_t *apn_buf = talloc_size(talloc_ctx, APN_MAXLEN);
|
||||
osmo_gsup_configure_wildcard_apn(gsup, apn_buf, APN_MAXLEN);
|
||||
}
|
||||
OSMO_ASSERT(apn_buf_size >= APN_MAXLEN);
|
||||
OSMO_ASSERT(apn_buf);
|
||||
/* FIXME: PDP infos - use more fine-grained access control
|
||||
instead of wildcard APN */
|
||||
osmo_gsup_configure_wildcard_apn(gsup, apn_buf, apn_buf_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
31
src/hlr.c
31
src/hlr.c
@@ -85,6 +85,8 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
|
||||
|
||||
llist_for_each_entry(co, &g_hlr->gs->clients, list) {
|
||||
struct osmo_gsup_message gsup = { };
|
||||
uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
|
||||
uint8_t apn[APN_MAXLEN];
|
||||
struct msgb *msg_out;
|
||||
uint8_t *peer;
|
||||
int peer_len;
|
||||
@@ -129,7 +131,8 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
|
||||
subscr->imsi, cn_domain == OSMO_GSUP_CN_DOMAIN_PS ? "PS" : "CS",
|
||||
osmo_quote_str(peer_compare, -1));
|
||||
|
||||
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, cn_domain, OTC_SELECT) != 0) {
|
||||
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, msisdn_enc,
|
||||
sizeof(msisdn_enc), apn, sizeof(apn), cn_domain) != 0) {
|
||||
LOGP(DLGSUP, LOGL_ERROR,
|
||||
"IMSI='%s': Cannot notify GSUP client; could not create gsup message "
|
||||
"for %s:%u\n", subscr->imsi,
|
||||
@@ -321,11 +324,7 @@ static int rx_send_auth_info(struct osmo_gsup_req *req)
|
||||
" Returning slightly inaccurate cause 'IMSI Unknown' via GSUP");
|
||||
return rc;
|
||||
case -ENOENT:
|
||||
osmo_gsup_req_respond_err(req,
|
||||
(req->gsup.cn_domain == OSMO_GSUP_CN_DOMAIN_CS) ?
|
||||
g_hlr->no_proxy_reject_cause.cs :
|
||||
g_hlr->no_proxy_reject_cause.ps,
|
||||
"IMSI unknown");
|
||||
osmo_gsup_req_respond_err(req, g_hlr->reject_cause, "IMSI unknown");
|
||||
return rc;
|
||||
default:
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_NET_FAIL, "failure to look up IMSI in db");
|
||||
@@ -383,7 +382,7 @@ static int rx_purge_ms_req(struct osmo_gsup_req *req)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rx_check_imei_req(struct osmo_gsup_req *req, bool final)
|
||||
static int rx_check_imei_req(struct osmo_gsup_req *req)
|
||||
{
|
||||
struct osmo_gsup_message gsup_reply;
|
||||
char imei[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1] = {0};
|
||||
@@ -437,7 +436,7 @@ static int rx_check_imei_req(struct osmo_gsup_req *req, bool final)
|
||||
.message_type = OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,
|
||||
.imei_result = OSMO_GSUP_IMEI_RESULT_ACK,
|
||||
};
|
||||
return osmo_gsup_req_respond(req, &gsup_reply, false, final);
|
||||
return osmo_gsup_req_respond(req, &gsup_reply, false, true);
|
||||
}
|
||||
|
||||
static char namebuf[255];
|
||||
@@ -558,7 +557,7 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
|
||||
lu_rx_gsup(req);
|
||||
break;
|
||||
case OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST:
|
||||
rx_check_imei_req(req, true);
|
||||
rx_check_imei_req(req);
|
||||
break;
|
||||
default:
|
||||
LOGP(DMAIN, LOGL_DEBUG, "Unhandled GSUP message type %s\n",
|
||||
@@ -569,12 +568,6 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dgsm_fallback_to_hlr(struct osmo_gsup_req *req) {
|
||||
LOGP(DDGSM, LOGL_DEBUG, "Fall back to HLR from DGSM for [%s]\n",
|
||||
osmo_gsup_message_type_name(req->gsup.message_type));
|
||||
rx_check_imei_req(req, false);
|
||||
}
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf("Usage: osmo-hlr\n");
|
||||
@@ -734,7 +727,7 @@ static void signal_hdlr(int signal)
|
||||
}
|
||||
|
||||
static const char vlr_copyright[] =
|
||||
"Copyright (C) 2016-2023 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
|
||||
"Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
|
||||
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
|
||||
"This is free software: you are free to change and redistribute it.\r\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\r\n";
|
||||
@@ -766,10 +759,8 @@ int main(int argc, char **argv)
|
||||
g_hlr->db_file_path = talloc_strdup(g_hlr, HLR_DEFAULT_DB_FILE_PATH);
|
||||
g_hlr->mslookup.server.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT);
|
||||
g_hlr->mslookup.client.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT);
|
||||
g_hlr->reject_cause.cs = GMM_CAUSE_IMSI_UNKNOWN;
|
||||
g_hlr->no_proxy_reject_cause.cs = GMM_CAUSE_IMSI_UNKNOWN;
|
||||
g_hlr->reject_cause.ps = GMM_CAUSE_IMSI_UNKNOWN;
|
||||
g_hlr->no_proxy_reject_cause.ps = GMM_CAUSE_IMSI_UNKNOWN;
|
||||
g_hlr->reject_cause = GMM_CAUSE_IMSI_UNKNOWN;
|
||||
g_hlr->no_proxy_reject_cause = GMM_CAUSE_IMSI_UNKNOWN;
|
||||
|
||||
/* Init default (call independent) SS session guard timeout value */
|
||||
g_hlr->ncss_guard_timeout = NCSS_GUARD_TIMEOUT_DEFAULT;
|
||||
|
||||
@@ -122,40 +122,9 @@ void ussd_route_del(struct hlr_ussd_route *rt)
|
||||
talloc_free(rt);
|
||||
}
|
||||
|
||||
static struct hlr_ussd_route *ussd_route_lookup_for_req(struct hlr *hlr, const struct ss_request *req)
|
||||
static struct hlr_ussd_route *ussd_route_lookup_7bit(struct hlr *hlr, const char *ussd_code)
|
||||
{
|
||||
const uint8_t cgroup = req->ussd_data_dcs >> 4;
|
||||
const uint8_t lang = req->ussd_data_dcs & 0x0f;
|
||||
char ussd_code[GSM0480_USSD_7BIT_STRING_LEN];
|
||||
struct hlr_ussd_route *rt;
|
||||
|
||||
ussd_code[0] = '\0';
|
||||
|
||||
/* We support only the Coding Group 0 (GSM 7-bit default alphabeet). In fact,
|
||||
* the USSD request is usually limited to [*#0-9], so we don't really need to
|
||||
* support other coding groups and languages. */
|
||||
switch (cgroup) {
|
||||
case 0:
|
||||
/* The Language is usually set to '1111'B (unspecified), but some UEs
|
||||
* are known to indicate '0000'B (German). */
|
||||
if (lang != 0x0f) {
|
||||
LOGP(DSS, LOGL_NOTICE, "USSD DataCodingScheme (0x%02x): "
|
||||
"the Language is usually set to 15 (unspecified), "
|
||||
"but the request indicates %u - ignoring this\n",
|
||||
req->ussd_data_dcs, lang);
|
||||
/* do not abort, attempt to decode as if it was '1111'B */
|
||||
}
|
||||
|
||||
gsm_7bit_decode_n_ussd(&ussd_code[0], sizeof(ussd_code),
|
||||
req->ussd_data, (req->ussd_data_len * 8) / 7);
|
||||
break;
|
||||
default:
|
||||
LOGP(DSS, LOGL_ERROR, "USSD DataCodingScheme (0x%02x): "
|
||||
"Coding Group %u is not supported, expecting Coding Group 0\n",
|
||||
req->ussd_data_dcs, cgroup);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
llist_for_each_entry(rt, &hlr->ussd_routes, list) {
|
||||
if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) {
|
||||
LOGP(DSS, LOGL_DEBUG, "Found %s '%s' (prefix '%s') for USSD "
|
||||
@@ -634,7 +603,7 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
|
||||
} else {
|
||||
/* VLR->EUSE: MO USSD. VLR is known ('conn'), EUSE is to be resolved */
|
||||
struct hlr_ussd_route *rt;
|
||||
rt = ussd_route_lookup_for_req(hlr, &req);
|
||||
rt = ussd_route_lookup_7bit(hlr, (const char *) req.ussd_text);
|
||||
if (rt) {
|
||||
if (rt->is_external) {
|
||||
ss->is_external = true;
|
||||
@@ -662,8 +631,7 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
|
||||
if (!ss) {
|
||||
LOGP(DSS, LOGL_ERROR, "%s/0x%08x: CONTINUE for unknown SS session\n",
|
||||
gsup->imsi, gsup->session_id);
|
||||
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_MSGT_INCOMP_P_STATE,
|
||||
"CONTINUE for unknown SS session");
|
||||
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_INV_MAND_INFO, "CONTINUE for unknown SS session");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -684,8 +652,6 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
|
||||
if (!ss) {
|
||||
LOGP(DSS, LOGL_ERROR, "%s/0x%08x: END for unknown SS session\n",
|
||||
gsup->imsi, gsup->session_id);
|
||||
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_MSGT_INCOMP_P_STATE,
|
||||
"END for unknown SS session");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -716,5 +682,4 @@ void rx_proc_ss_error(struct osmo_gsup_req *req)
|
||||
{
|
||||
LOGP(DSS, LOGL_NOTICE, "%s/0x%08x: Process SS ERROR (%s)\n", req->gsup.imsi, req->gsup.session_id,
|
||||
osmo_gsup_session_state_name(req->gsup.session_state));
|
||||
osmo_gsup_req_free(req);
|
||||
}
|
||||
|
||||
270
src/hlr_vty.c
270
src/hlr_vty.c
@@ -26,12 +26,9 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/stats.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
@@ -106,202 +103,18 @@ DEFUN(cfg_gsup,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_node ps_node = {
|
||||
PS_NODE,
|
||||
"%s(config-hlr-ps)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_ps,
|
||||
cfg_ps_cmd,
|
||||
"ps",
|
||||
"Configure the PS options")
|
||||
{
|
||||
vty->node = PS_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_node ps_pdp_profiles_node = {
|
||||
PS_PDP_PROFILES_NODE,
|
||||
"%s(config-hlr-ps-pdp-profiles)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_ps_pdp_profiles,
|
||||
cfg_ps_pdp_profiles_cmd,
|
||||
"pdp-profiles default",
|
||||
"Define a PDP profile set.\n"
|
||||
"Define the global default profile.\n")
|
||||
{
|
||||
g_hlr->ps.pdp_profile.enabled = true;
|
||||
|
||||
vty->node = PS_PDP_PROFILES_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_ps_pdp_profiles,
|
||||
cfg_no_ps_pdp_profiles_cmd,
|
||||
"no pdp-profiles default",
|
||||
NO_STR
|
||||
"Delete PDP profile.\n"
|
||||
"Unique identifier for this PDP profile set.\n")
|
||||
{
|
||||
g_hlr->ps.pdp_profile.enabled = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct cmd_node ps_pdp_profiles_profile_node = {
|
||||
PS_PDP_PROFILES_PROFILE_NODE,
|
||||
"%s(config-hlr-ps-pdp-profile)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
|
||||
/* context_id == 0 means the slot is free */
|
||||
struct osmo_gsup_pdp_info *get_pdp_profile(uint8_t context_id)
|
||||
{
|
||||
for (int i = 0; i < OSMO_GSUP_MAX_NUM_PDP_INFO; i++) {
|
||||
struct osmo_gsup_pdp_info *info = &g_hlr->ps.pdp_profile.pdp_infos[i];
|
||||
if (info->context_id == context_id)
|
||||
return info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct osmo_gsup_pdp_info *create_pdp_profile(uint8_t context_id)
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info = get_pdp_profile(0);
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->context_id = context_id;
|
||||
info->have_info = 1;
|
||||
|
||||
g_hlr->ps.pdp_profile.num_pdp_infos++;
|
||||
return info;
|
||||
}
|
||||
|
||||
void destroy_pdp_profile(struct osmo_gsup_pdp_info *info)
|
||||
{
|
||||
info->context_id = 0;
|
||||
if (info->apn_enc)
|
||||
talloc_free((void *) info->apn_enc);
|
||||
|
||||
g_hlr->ps.pdp_profile.num_pdp_infos--;
|
||||
memset(info, 0, sizeof(*info));
|
||||
}
|
||||
|
||||
DEFUN(cfg_ps_pdp_profiles_profile,
|
||||
cfg_ps_pdp_profiles_profile_cmd,
|
||||
"profile <1-10>",
|
||||
"Configure a PDP profile\n"
|
||||
"Unique PDP context identifier. The lowest profile will be used as default context.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info;
|
||||
uint8_t context_id = atoi(argv[0]);
|
||||
|
||||
info = get_pdp_profile(context_id);
|
||||
if (!info) {
|
||||
info = create_pdp_profile(context_id);
|
||||
if (!info) {
|
||||
vty_out(vty, "Failed to create profile %d!%s", context_id, VTY_NEWLINE);
|
||||
return CMD_ERR_INCOMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
vty->node = PS_PDP_PROFILES_PROFILE_NODE;
|
||||
vty->index = info;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_ps_pdp_profiles_profile,
|
||||
cfg_no_ps_pdp_profiles_profile_cmd,
|
||||
"no profile <1-10>",
|
||||
NO_STR
|
||||
"Delete a PDP profile\n"
|
||||
"Unique PDP context identifier. The lowest profile will be used as default context.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info;
|
||||
uint8_t context_id = atoi(argv[0]);
|
||||
|
||||
info = get_pdp_profile(context_id);
|
||||
if (info)
|
||||
destroy_pdp_profile(info);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ps_pdp_profile_apn, cfg_ps_pdp_profile_apn_cmd,
|
||||
"apn ID",
|
||||
"Configure the APN.\n"
|
||||
"APN name or * for wildcard apn.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info = vty->index;
|
||||
const char *apn_name = argv[0];
|
||||
|
||||
/* apn encoded takes one more byte than strlen() */
|
||||
size_t apn_enc_len = strlen(apn_name) + 1;
|
||||
uint8_t *apn_enc;
|
||||
int ret;
|
||||
|
||||
if (apn_enc_len > APN_MAXLEN) {
|
||||
vty_out(vty, "APN name is too long '%s'. Max is %d!%s", apn_name, APN_MAXLEN, VTY_NEWLINE);
|
||||
return CMD_ERR_INCOMPLETE;
|
||||
}
|
||||
|
||||
info->apn_enc = apn_enc = (uint8_t *) talloc_zero_size(g_hlr, apn_enc_len);
|
||||
ret = info->apn_enc_len = osmo_apn_from_str(apn_enc, apn_enc_len, apn_name);
|
||||
if (ret < 0) {
|
||||
talloc_free(apn_enc);
|
||||
info->apn_enc = NULL;
|
||||
info->apn_enc_len = 0;
|
||||
vty_out(vty, "Invalid APN name %s!", apn_name);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_ps_pdp_profile_apn, cfg_no_ps_pdp_profile_apn_cmd,
|
||||
"no apn",
|
||||
NO_STR
|
||||
"Delete the APN.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info = vty->index;
|
||||
if (info->apn_enc) {
|
||||
talloc_free((void *) info->apn_enc);
|
||||
info->apn_enc = NULL;
|
||||
info->apn_enc_len = 0;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int config_write_hlr(struct vty *vty)
|
||||
{
|
||||
vty_out(vty, "hlr%s", VTY_NEWLINE);
|
||||
|
||||
if (g_hlr->reject_cause.cs != GMM_CAUSE_IMSI_UNKNOWN)
|
||||
vty_out(vty, " reject-cause not-found cs %s%s",
|
||||
if (g_hlr->reject_cause != GMM_CAUSE_IMSI_UNKNOWN)
|
||||
vty_out(vty, " reject-cause not-found %s%s",
|
||||
get_value_string_or_null(gsm48_gmm_cause_vty_names,
|
||||
(uint32_t) g_hlr->reject_cause.cs), VTY_NEWLINE);
|
||||
if (g_hlr->reject_cause.ps != GMM_CAUSE_IMSI_UNKNOWN)
|
||||
vty_out(vty, " reject-cause not-found ps %s%s",
|
||||
(uint32_t) g_hlr->reject_cause), VTY_NEWLINE);
|
||||
if (g_hlr->no_proxy_reject_cause != GMM_CAUSE_IMSI_UNKNOWN)
|
||||
vty_out(vty, " reject-cause no-proxy %s%s",
|
||||
get_value_string_or_null(gsm48_gmm_cause_vty_names,
|
||||
(uint32_t) g_hlr->reject_cause.ps), VTY_NEWLINE);
|
||||
if (g_hlr->no_proxy_reject_cause.cs != GMM_CAUSE_IMSI_UNKNOWN)
|
||||
vty_out(vty, " reject-cause no-proxy cs %s%s",
|
||||
get_value_string_or_null(gsm48_gmm_cause_vty_names,
|
||||
(uint32_t) g_hlr->no_proxy_reject_cause.cs), VTY_NEWLINE);
|
||||
if (g_hlr->no_proxy_reject_cause.ps != GMM_CAUSE_IMSI_UNKNOWN)
|
||||
vty_out(vty, " reject-cause no-proxy ps %s%s",
|
||||
get_value_string_or_null(gsm48_gmm_cause_vty_names,
|
||||
(uint32_t) g_hlr->no_proxy_reject_cause.ps), VTY_NEWLINE);
|
||||
(uint32_t) g_hlr->no_proxy_reject_cause), VTY_NEWLINE);
|
||||
if (g_hlr->store_imei)
|
||||
vty_out(vty, " store-imei%s", VTY_NEWLINE);
|
||||
if (g_hlr->db_file_path && strcmp(g_hlr->db_file_path, HLR_DEFAULT_DB_FILE_PATH))
|
||||
@@ -336,37 +149,6 @@ static int config_write_hlr_gsup(struct vty *vty)
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_hlr_ps(struct vty *vty)
|
||||
{
|
||||
vty_out(vty, " ps%s", VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_hlr_ps_pdp_profiles(struct vty *vty)
|
||||
{
|
||||
char apn[APN_MAXLEN + 1] = {};
|
||||
|
||||
if (!g_hlr->ps.pdp_profile.enabled)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
vty_out(vty, " pdp-profiles default%s", VTY_NEWLINE);
|
||||
for (int i = 0; i < g_hlr->ps.pdp_profile.num_pdp_infos; i++) {
|
||||
struct osmo_gsup_pdp_info *pdp_info = &g_hlr->ps.pdp_profile.pdp_infos[i];
|
||||
if (!pdp_info->context_id)
|
||||
continue;
|
||||
|
||||
vty_out(vty, " profile %d%s", pdp_info->context_id, VTY_NEWLINE);
|
||||
if (!pdp_info->have_info)
|
||||
continue;
|
||||
|
||||
if (pdp_info->apn_enc && pdp_info->apn_enc_len) {
|
||||
osmo_apn_to_str(apn, pdp_info->apn_enc, pdp_info->apn_enc_len);
|
||||
vty_out(vty, " apn %s%s", apn, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
|
||||
{
|
||||
const struct ipa_server_conn *isc = conn->conn;
|
||||
@@ -622,27 +404,17 @@ DEFUN(cfg_ncss_guard_timeout, cfg_ncss_guard_timeout_cmd,
|
||||
DEFUN(cfg_reject_cause, cfg_reject_cause_cmd,
|
||||
"reject-cause TYPE CAUSE", "") /* Dynamically Generated */
|
||||
{
|
||||
int cause_code = get_string_value(gsm48_gmm_cause_vty_names, argv[2]);
|
||||
int cause_code = get_string_value(gsm48_gmm_cause_vty_names, argv[1]);
|
||||
OSMO_ASSERT(cause_code >= 0);
|
||||
|
||||
if (strcmp(argv[0], "not-found") == 0) {
|
||||
if (strcmp(argv[1], "cs") == 0)
|
||||
g_hlr->reject_cause.cs = (enum gsm48_gmm_cause) cause_code;
|
||||
else
|
||||
g_hlr->reject_cause.ps = (enum gsm48_gmm_cause) cause_code;
|
||||
}
|
||||
if (strcmp(argv[0], "no-proxy") == 0) {
|
||||
if (strcmp(argv[1], "cs") == 0)
|
||||
g_hlr->no_proxy_reject_cause.cs = (enum gsm48_gmm_cause) cause_code;
|
||||
else
|
||||
g_hlr->no_proxy_reject_cause.ps = (enum gsm48_gmm_cause) cause_code;
|
||||
}
|
||||
if (strcmp(argv[0], "not-found") == 0)
|
||||
g_hlr->reject_cause = (enum gsm48_gmm_cause) cause_code;
|
||||
if (strcmp(argv[0], "no-proxy") == 0)
|
||||
g_hlr->no_proxy_reject_cause = (enum gsm48_gmm_cause) cause_code;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DEFUN(cfg_store_imei, cfg_store_imei_cmd,
|
||||
"store-imei",
|
||||
"Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send"
|
||||
@@ -740,7 +512,7 @@ void hlr_vty_init(void *hlr_ctx)
|
||||
cfg_reject_cause_cmd.string =
|
||||
vty_cmd_string_from_valstr(hlr_ctx,
|
||||
gsm48_gmm_cause_vty_names,
|
||||
"reject-cause (not-found|no-proxy) (cs|ps) (", "|", ")",
|
||||
"reject-cause (not-found|no-proxy) (", "|", ")",
|
||||
VTY_DO_LOWER);
|
||||
|
||||
cfg_reject_cause_cmd.doc =
|
||||
@@ -748,9 +520,7 @@ void hlr_vty_init(void *hlr_ctx)
|
||||
gsm48_gmm_cause_vty_descs,
|
||||
"GSUP/GMM cause to be sent\n"
|
||||
"in the case the IMSI could not be found in the database\n"
|
||||
"in the case no remote HLR reponded to mslookup GSUP request\n"
|
||||
"for CS domain\n"
|
||||
"for PS domain\n",
|
||||
"in the case no remote HLR reponded to mslookup GSUP request\n",
|
||||
"\n", "", 0);
|
||||
|
||||
logging_vty_add_cmds();
|
||||
@@ -768,20 +538,6 @@ void hlr_vty_init(void *hlr_ctx)
|
||||
install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
|
||||
install_element(GSUP_NODE, &cfg_hlr_gsup_ipa_name_cmd);
|
||||
|
||||
/* PS */
|
||||
install_node(&ps_node, config_write_hlr_ps);
|
||||
install_element(HLR_NODE, &cfg_ps_cmd);
|
||||
|
||||
install_node(&ps_pdp_profiles_node, config_write_hlr_ps_pdp_profiles);
|
||||
install_element(PS_NODE, &cfg_ps_pdp_profiles_cmd);
|
||||
install_element(PS_NODE, &cfg_no_ps_pdp_profiles_cmd);
|
||||
|
||||
install_node(&ps_pdp_profiles_profile_node, NULL);
|
||||
install_element(PS_PDP_PROFILES_NODE, &cfg_ps_pdp_profiles_profile_cmd);
|
||||
install_element(PS_PDP_PROFILES_NODE, &cfg_no_ps_pdp_profiles_profile_cmd);
|
||||
install_element(PS_PDP_PROFILES_PROFILE_NODE, &cfg_ps_pdp_profile_apn_cmd);
|
||||
install_element(PS_PDP_PROFILES_PROFILE_NODE, &cfg_no_ps_pdp_profile_apn_cmd);
|
||||
|
||||
install_element(HLR_NODE, &cfg_database_cmd);
|
||||
|
||||
install_element(HLR_NODE, &cfg_euse_cmd);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* OsmoHLR subscriber management VTY implementation */
|
||||
/* (C) 2017-2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -77,8 +77,8 @@ static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t
|
||||
static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
{
|
||||
int rc;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
|
||||
vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);
|
||||
|
||||
@@ -137,12 +137,12 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
|
||||
if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) {
|
||||
vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE);
|
||||
aud2g = (struct osmo_sub_auth_data2){};
|
||||
aud2g = (struct osmo_sub_auth_data){};
|
||||
}
|
||||
|
||||
if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) {
|
||||
vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE);
|
||||
aud3g = (struct osmo_sub_auth_data2){};
|
||||
aud3g = (struct osmo_sub_auth_data){};
|
||||
}
|
||||
|
||||
if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
|
||||
@@ -154,10 +154,9 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
|
||||
if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) {
|
||||
vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
|
||||
vty_out(vty, " K=%s%s",
|
||||
osmo_hexdump_nospc(aud3g.u.umts.k, aud3g.u.umts.k_len), VTY_NEWLINE);
|
||||
vty_out(vty, " K=%s%s", hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE);
|
||||
vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
|
||||
osmo_hexdump_nospc(aud3g.u.umts.opc, aud3g.u.umts.opc_len), VTY_NEWLINE);
|
||||
hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
|
||||
vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen);
|
||||
if (aud3g.u.umts.sqn)
|
||||
vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);
|
||||
@@ -182,11 +181,8 @@ static void subscr_dump_summary_vty(struct hlr_subscriber *subscr, void *data)
|
||||
vty_out(vty," ------------- ");
|
||||
}
|
||||
vty_out(vty, " %-2s%-2s ", subscr->nam_cs ? "CS" : "", subscr->nam_ps ? "PS" : "");
|
||||
if (subscr->last_lu_seen) {
|
||||
/* VLR Number is max length 32, possibly truncate here */
|
||||
vty_out(vty, " %.22s ", subscr->vlr_number);
|
||||
if (subscr->last_lu_seen)
|
||||
dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, true);
|
||||
}
|
||||
vty_out_newline(vty);
|
||||
}
|
||||
|
||||
@@ -221,8 +217,8 @@ static void dump_summary_table_vty(struct vty *vty, bool header, bool show_ls)
|
||||
{
|
||||
const char *texts = "ID MSISDN IMSI IMEI NAM";
|
||||
const char *lines = "----- ------------ ---------------- ---------------- -----";
|
||||
const char *ls_text = " VLR_NUMBER LAST SEEN ";
|
||||
const char *ls_line = " --------------------- ---------------------";
|
||||
const char *ls_text = " LAST SEEN";
|
||||
const char *ls_line = " ------------";
|
||||
if (header) {
|
||||
if (!show_ls)
|
||||
vty_out(vty, "%s%s%s%s", texts, VTY_NEWLINE, lines, VTY_NEWLINE);
|
||||
@@ -464,27 +460,20 @@ static bool is_hexkey_valid(struct vty *vty, const char *label,
|
||||
return false;
|
||||
}
|
||||
|
||||
#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor-2g)"
|
||||
#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor)"
|
||||
#define AUTH_ALG_TYPES_2G_HELP \
|
||||
"Use COMP128v1 algorithm\n" \
|
||||
"Use COMP128v2 algorithm\n" \
|
||||
"Use COMP128v3 algorithm\n" \
|
||||
"Use XOR-2G algorithm\n"
|
||||
"Use XOR algorithm\n"
|
||||
|
||||
#define AUTH_ALG_TYPES_3G "(milenage|tuak)"
|
||||
#define AUTH_ALG_TYPES_3G "milenage"
|
||||
#define AUTH_ALG_TYPES_3G_HELP \
|
||||
"Use Milenage algorithm\n" \
|
||||
"Use TUAK algorithm\n"
|
||||
"Use Milenage algorithm\n"
|
||||
|
||||
bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
|
||||
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc)
|
||||
int *minlen, int *maxlen)
|
||||
{
|
||||
/* Default: no OP[c]. True for all 2G algorithms, and 3G-XOR. Overridden below for real 3G AKA algorithms. */
|
||||
if (minlen_opc)
|
||||
*minlen_opc = 0;
|
||||
if (maxlen_opc)
|
||||
*maxlen_opc = 0;
|
||||
|
||||
if (!strcasecmp(alg_str, "none")) {
|
||||
*algo = OSMO_AUTH_ALG_NONE;
|
||||
*minlen = *maxlen = 0;
|
||||
@@ -497,28 +486,13 @@ bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
|
||||
} else if (!strcasecmp(alg_str, "comp128v3")) {
|
||||
*algo = OSMO_AUTH_ALG_COMP128v3;
|
||||
*minlen = *maxlen = A38_COMP128_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "xor-3g")) {
|
||||
*algo = OSMO_AUTH_ALG_XOR_3G;
|
||||
} else if (!strcasecmp(alg_str, "xor")) {
|
||||
*algo = OSMO_AUTH_ALG_XOR;
|
||||
*minlen = A38_XOR_MIN_KEY_LEN;
|
||||
*maxlen = A38_XOR_MAX_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "xor-2g")) {
|
||||
*algo = OSMO_AUTH_ALG_XOR_2G;
|
||||
*minlen = *maxlen = A38_XOR2G_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "milenage")) {
|
||||
*algo = OSMO_AUTH_ALG_MILENAGE;
|
||||
*minlen = *maxlen = MILENAGE_KEY_LEN;
|
||||
if (minlen_opc)
|
||||
*minlen_opc = MILENAGE_KEY_LEN;
|
||||
if (maxlen_opc)
|
||||
*maxlen_opc = MILENAGE_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "tuak")) {
|
||||
*algo = OSMO_AUTH_ALG_TUAK;
|
||||
*minlen = 16;
|
||||
*maxlen = 32;
|
||||
if (minlen_opc)
|
||||
*minlen_opc = 32;
|
||||
if (maxlen_opc)
|
||||
*maxlen_opc = 32;
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
@@ -574,7 +548,7 @@ DEFUN(subscriber_aud2g,
|
||||
.u.gsm.ki = ki,
|
||||
};
|
||||
|
||||
if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
|
||||
if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -633,21 +607,21 @@ DEFUN(subscriber_aud3g,
|
||||
SUBSCR_UPDATE_HELP
|
||||
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
|
||||
AUTH_ALG_TYPES_3G_HELP
|
||||
"Set Encryption Key K\n" "K as 32/64 hexadecimal characters\n"
|
||||
"Set OP key\n" "Set OPC key\n" "OP or OPC as 32/64 hexadecimal characters\n"
|
||||
"Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
|
||||
"Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
|
||||
"Set IND bit length\n" "IND bit length value (default: 5)\n")
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
int minlen = 0, minlen_opc = 0;
|
||||
int maxlen = 0, maxlen_opc = 0;
|
||||
int minlen = 0;
|
||||
int maxlen = 0;
|
||||
int rc;
|
||||
const char *id_type = argv[0];
|
||||
const char *id = argv[1];
|
||||
const char *alg_type = argv[2];
|
||||
const char *k = argv[3];
|
||||
bool opc_is_op = (strcasecmp("op", argv[4]) == 0);
|
||||
const char *op_opc = argv[5];
|
||||
int ind_bitlen = argc > 7 ? atoi(argv[7]) : 5;
|
||||
const char *alg_type = AUTH_ALG_TYPES_3G;
|
||||
const char *k = argv[2];
|
||||
bool opc_is_op = (strcasecmp("op", argv[3]) == 0);
|
||||
const char *op_opc = argv[4];
|
||||
int ind_bitlen = argc > 6? atoi(argv[6]) : 5;
|
||||
struct sub_auth_data_str aud3g = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.u.umts = {
|
||||
@@ -658,7 +632,7 @@ DEFUN(subscriber_aud3g,
|
||||
},
|
||||
};
|
||||
|
||||
if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
|
||||
if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -666,7 +640,8 @@ DEFUN(subscriber_aud3g,
|
||||
if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
|
||||
return CMD_WARNING;
|
||||
|
||||
if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc, minlen_opc, maxlen_opc))
|
||||
if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc,
|
||||
MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
|
||||
return CMD_WARNING;
|
||||
|
||||
if (get_subscr_by_argv(vty, id_type, id, &subscr))
|
||||
@@ -684,11 +659,11 @@ DEFUN(subscriber_aud3g,
|
||||
|
||||
DEFUN(subscriber_aud3g_xor,
|
||||
subscriber_aud3g_xor_cmd,
|
||||
SUBSCR_UPDATE "aud3g xor-3g k K"
|
||||
SUBSCR_UPDATE "aud3g xor k K"
|
||||
" [ind-bitlen] [<0-28>]",
|
||||
SUBSCR_UPDATE_HELP
|
||||
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
|
||||
"Use XOR-3G algorithm\n"
|
||||
"Use XOR algorithm\n"
|
||||
"Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
|
||||
"Set IND bit length\n" "IND bit length value (default: 5)\n")
|
||||
{
|
||||
@@ -710,8 +685,8 @@ DEFUN(subscriber_aud3g_xor,
|
||||
},
|
||||
};
|
||||
|
||||
if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen, NULL, NULL)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor-3g", VTY_NEWLINE);
|
||||
if (!auth_algo_parse("xor", &aud3g.algo, &minlen, &maxlen)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
|
||||
12
src/lu_fsm.c
12
src/lu_fsm.c
@@ -136,8 +136,7 @@ static void lu_start(struct osmo_gsup_req *update_location_req)
|
||||
}
|
||||
|
||||
if (db_subscr_get_by_imsi(g_hlr->dbc, update_location_req->gsup.imsi, &lu->subscr) < 0) {
|
||||
lu_failure(lu, (lu->is_ps) ? g_hlr->reject_cause.ps : g_hlr->reject_cause.cs,
|
||||
"Subscriber does not exist");
|
||||
lu_failure(lu, g_hlr->reject_cause, "Subscriber does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -242,11 +241,13 @@ static void lu_fsm_wait_insert_data_result_onenter(struct osmo_fsm_inst *fi, uin
|
||||
struct lu *lu = fi->priv;
|
||||
struct hlr_subscriber *subscr = &lu->subscr;
|
||||
struct osmo_gsup_message gsup;
|
||||
uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
|
||||
uint8_t apn[APN_MAXLEN];
|
||||
|
||||
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi,
|
||||
subscr->msisdn,
|
||||
lu->is_ps ? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS,
|
||||
OTC_SELECT)) {
|
||||
subscr->msisdn, msisdn_enc, sizeof(msisdn_enc),
|
||||
apn, sizeof(apn),
|
||||
lu->is_ps? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS)) {
|
||||
lu_failure(lu, GMM_CAUSE_NET_FAIL, "cannot encode Insert Subscriber Data message");
|
||||
return;
|
||||
}
|
||||
@@ -276,7 +277,6 @@ void lu_fsm_wait_insert_data_result(struct osmo_fsm_inst *fi, uint32_t event, vo
|
||||
|
||||
case OSMO_GSUP_MSGT_INSERT_DATA_ERROR:
|
||||
lu_failure(lu, GMM_CAUSE_NET_FAIL, "Rx %s", osmo_gsup_message_type_name(req->gsup.message_type));
|
||||
osmo_gsup_req_free(req);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read chapter "Library interface versions" of the libtool documentation
|
||||
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
|
||||
LIBVERSION=1:1:0
|
||||
LIBVERSION=1:0:0
|
||||
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include
|
||||
AM_CFLAGS = -fPIC -Wall $(PCSC_CFLAGS) $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS)
|
||||
|
||||
@@ -45,7 +45,6 @@ static char *domain_from_query(void *ctx, const struct osmo_mslookup_query *quer
|
||||
/* Get id from query */
|
||||
switch (query->id.type) {
|
||||
case OSMO_MSLOOKUP_ID_IMSI:
|
||||
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
|
||||
id = query->id.imsi;
|
||||
break;
|
||||
case OSMO_MSLOOKUP_ID_MSISDN:
|
||||
|
||||
@@ -91,7 +91,6 @@ const struct value_string osmo_mslookup_id_type_names[] = {
|
||||
{ OSMO_MSLOOKUP_ID_NONE, "none" },
|
||||
{ OSMO_MSLOOKUP_ID_IMSI, "imsi" },
|
||||
{ OSMO_MSLOOKUP_ID_MSISDN, "msisdn" },
|
||||
{ OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED, "imsiauth" },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -135,7 +134,6 @@ bool osmo_mslookup_id_valid(const struct osmo_mslookup_id *id)
|
||||
{
|
||||
switch (id->type) {
|
||||
case OSMO_MSLOOKUP_ID_IMSI:
|
||||
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
|
||||
return osmo_imsi_str_valid(id->imsi);
|
||||
case OSMO_MSLOOKUP_ID_MSISDN:
|
||||
return osmo_msisdn_str_valid(id->msisdn);
|
||||
@@ -159,7 +157,6 @@ size_t osmo_mslookup_id_name_buf(char *buf, size_t buflen, const struct osmo_msl
|
||||
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
|
||||
switch (id->type) {
|
||||
case OSMO_MSLOOKUP_ID_IMSI:
|
||||
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
|
||||
OSMO_STRBUF_PRINTF(sb, "%s", id->imsi);
|
||||
break;
|
||||
case OSMO_MSLOOKUP_ID_MSISDN:
|
||||
@@ -301,7 +298,6 @@ int osmo_mslookup_query_init_from_domain_str(struct osmo_mslookup_query *q, cons
|
||||
id = second_last_dot + 1;
|
||||
switch (q->id.type) {
|
||||
case OSMO_MSLOOKUP_ID_IMSI:
|
||||
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
|
||||
rc = token(q->id.imsi, sizeof(q->id.imsi), id, last_dot);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@@ -154,20 +154,16 @@ void osmo_mslookup_client_rx_result(struct osmo_mslookup_client *client, uint32_
|
||||
if (result->rc != OSMO_MSLOOKUP_RC_RESULT)
|
||||
return;
|
||||
|
||||
/* If the client wants to see all results, send this result now */
|
||||
if (req->handling.search_all && result->age > 0)
|
||||
req->handling.result_cb(client, request_handle, &req->query, result);
|
||||
|
||||
/* If we already stored an earlier successful result, keep that if its age is younger. */
|
||||
if (req->result.rc == OSMO_MSLOOKUP_RC_RESULT
|
||||
&& result->age > req->result.age)
|
||||
&& result->age >= req->result.age)
|
||||
return;
|
||||
|
||||
req->result = *result;
|
||||
|
||||
/* If age == 0, it doesn't get any better, so return the result immediately. */
|
||||
if (req->result.age == 0) {
|
||||
osmo_mslookup_request_send_result(req, !req->handling.search_all);
|
||||
osmo_mslookup_request_send_result(req, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,10 +133,6 @@ CSV_HEADERS "\n"
|
||||
" 1000-5000@sip.voice.123.msisdn Same, but silent for first second\n"
|
||||
" 10000-@smpp.sms.567.msisdn Return 1 result after 10 seconds\n"
|
||||
"\n"
|
||||
"--search-all -A\n"
|
||||
" Do not stop when a response with age of zero comes in.\n"
|
||||
" This can be used to \"search\" the entire dGSM network if for\n"
|
||||
" example there is a need to track down so-called \"evil twin\" hlr entries.\n"
|
||||
"--format -f csv (default)\n"
|
||||
" Format result lines in CSV format.\n"
|
||||
"--no-csv-headers -H\n"
|
||||
@@ -200,7 +196,6 @@ enum result_format {
|
||||
};
|
||||
|
||||
static struct {
|
||||
bool search_all;
|
||||
bool daemon;
|
||||
struct osmo_sockaddr_str mdns_addr;
|
||||
uint32_t min_delay;
|
||||
@@ -424,9 +419,9 @@ static void socket_client_close(struct socket_client *c)
|
||||
{
|
||||
struct osmo_fd *ofd = &c->ofd;
|
||||
|
||||
osmo_fd_unregister(ofd);
|
||||
close(ofd->fd);
|
||||
ofd->fd = -1;
|
||||
osmo_fd_unregister(ofd);
|
||||
|
||||
llist_del(&c->entry);
|
||||
talloc_free(c);
|
||||
@@ -566,9 +561,9 @@ void socket_close(void)
|
||||
llist_for_each_entry_safe(c, n, &globals.socket_clients, entry)
|
||||
socket_client_close(c);
|
||||
if (osmo_fd_is_registered(&globals.socket_ofd)) {
|
||||
osmo_fd_unregister(&globals.socket_ofd);
|
||||
close(globals.socket_ofd.fd);
|
||||
globals.socket_ofd.fd = -1;
|
||||
osmo_fd_unregister(&globals.socket_ofd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,7 +628,6 @@ void start_query_str(const char *query_str)
|
||||
const char *domain_str = query_str;
|
||||
char *at;
|
||||
struct osmo_mslookup_query_handling h = {
|
||||
.search_all = cmdline_opts.search_all,
|
||||
.min_wait_milliseconds = cmdline_opts.min_delay,
|
||||
.result_timeout_milliseconds = cmdline_opts.timeout,
|
||||
.result_cb = mslookup_result_cb,
|
||||
@@ -736,7 +730,6 @@ int main(int argc, char **argv)
|
||||
int option_index = 0;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "search-all", 0, 0, 'A' },
|
||||
{ "format", 1, 0, 'f' },
|
||||
{ "no-csv-headers", 0, 0, 'H' },
|
||||
{ "daemon", 0, 0, 'd' },
|
||||
@@ -762,15 +755,12 @@ int main(int argc, char **argv)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
c = getopt_long(argc, argv, "Af:Hdm:M:D:t:T:s:SqhV", long_options, &option_index);
|
||||
c = getopt_long(argc, argv, "f:Hdm:M:D:t:T:s:SqhV", long_options, &option_index);
|
||||
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'A':
|
||||
cmdline_opts.search_all = true;
|
||||
break;
|
||||
case 'f':
|
||||
cmdline_opts.format_str = optarg;
|
||||
break;
|
||||
|
||||
@@ -192,37 +192,12 @@ static void mslookup_server_rx_hlr_gsup(const struct osmo_mslookup_query *query,
|
||||
{
|
||||
const struct mslookup_service_host *host;
|
||||
int rc;
|
||||
bool exists = false;
|
||||
bool auth_imsi_only = false;
|
||||
bool created_on_demand = false;
|
||||
|
||||
switch (query->id.type) {
|
||||
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
|
||||
auth_imsi_only = true;
|
||||
case OSMO_MSLOOKUP_ID_IMSI:
|
||||
/* Entries that have been created by subscriber create on demand
|
||||
will have default msisdn length. and will not have any vlr_number entry.
|
||||
We should not answer for these, unless they have CS/PS service. */
|
||||
if (g_hlr->mslookup.ignore_created_on_demand) {
|
||||
rc = db_subscr_is_created_on_demand_by_imsi(g_hlr->dbc, query->id.imsi,
|
||||
g_hlr->subscr_create_on_demand_rand_msisdn_len);
|
||||
if (!rc) {
|
||||
exists = true;
|
||||
created_on_demand = true;
|
||||
rc = -ENOENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc = db_subscr_exists_by_imsi(g_hlr->dbc, query->id.imsi);
|
||||
if (g_hlr->mslookup.auth_imsi_only || auth_imsi_only) {
|
||||
if (!rc)
|
||||
exists = true;
|
||||
rc = db_subscr_authorized_by_imsi(g_hlr->dbc, query->id.imsi);
|
||||
}
|
||||
break;
|
||||
case OSMO_MSLOOKUP_ID_MSISDN:
|
||||
rc = db_subscr_exists_by_msisdn(g_hlr->dbc, query->id.msisdn);
|
||||
/* FIXME: The log message below might not match */
|
||||
break;
|
||||
default:
|
||||
LOGP(DMSLOOKUP, LOGL_ERROR, "Unknown mslookup ID type: %d\n", query->id.type);
|
||||
@@ -231,11 +206,8 @@ static void mslookup_server_rx_hlr_gsup(const struct osmo_mslookup_query *query,
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
LOGP(DMSLOOKUP, LOGL_DEBUG, "%s: %s%s%s in local HLR\n",
|
||||
osmo_mslookup_result_name_c(OTC_SELECT, query, NULL),
|
||||
(exists) ? "exists but" : "does not exist",
|
||||
(created_on_demand) ? " is created on demand and since untouched" : "",
|
||||
(exists && !created_on_demand) ? " is not authorized" : "");
|
||||
LOGP(DMSLOOKUP, LOGL_DEBUG, "%s: does not exist in local HLR\n",
|
||||
osmo_mslookup_result_name_c(OTC_SELECT, query, NULL));
|
||||
*result = not_found;
|
||||
return;
|
||||
}
|
||||
|
||||
19
src/proxy.c
19
src/proxy.c
@@ -92,11 +92,7 @@ static void proxy_pending_req_remote_hlr_connect_result(struct osmo_gsup_req *re
|
||||
osmo_gsup_req_respond(req, &gsup_reply, false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
osmo_gsup_req_respond_err(req,
|
||||
(req->gsup.cn_domain == OSMO_GSUP_CN_DOMAIN_CS) ?
|
||||
g_hlr->no_proxy_reject_cause.cs :
|
||||
g_hlr->no_proxy_reject_cause.ps,
|
||||
osmo_gsup_req_respond_err(req, g_hlr->no_proxy_reject_cause,
|
||||
"Proxy: Failed to connect to home HLR");
|
||||
return;
|
||||
}
|
||||
@@ -117,19 +113,6 @@ static bool proxy_deferred_gsup_req_waiting(struct proxy *proxy, const char *ims
|
||||
return false;
|
||||
}
|
||||
|
||||
struct osmo_gsup_req *proxy_deferred_gsup_req_get_by_imsi(struct proxy *proxy, const char *imsi)
|
||||
{
|
||||
struct proxy_pending_gsup_req *p;
|
||||
OSMO_ASSERT(imsi);
|
||||
|
||||
llist_for_each_entry(p, &proxy->pending_gsup_reqs, entry) {
|
||||
if (strcmp(p->req->gsup.imsi, imsi))
|
||||
continue;
|
||||
return p->req;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Result of looking for remote HLR. If it failed, pass remote_hlr as NULL. On failure, the remote_hlr may be passed
|
||||
* NULL. */
|
||||
static void proxy_deferred_gsup_req_pop(struct proxy *proxy, const char *imsi, struct remote_hlr *remote_hlr)
|
||||
|
||||
@@ -2,12 +2,12 @@ SUBDIRS = gen_ts_55_205_test_sets
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(NULL)
|
||||
@@ -30,8 +30,8 @@ auc_test_SOURCES = \
|
||||
$(NULL)
|
||||
|
||||
auc_test_LDADD = \
|
||||
$(top_builddir)/src/auc.o \
|
||||
$(top_builddir)/src/logging.o \
|
||||
$(top_srcdir)/src/auc.c \
|
||||
$(top_srcdir)/src/logging.c \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(NULL)
|
||||
@@ -41,8 +41,8 @@ auc_ts_55_205_test_sets_SOURCES = \
|
||||
$(NULL)
|
||||
|
||||
auc_ts_55_205_test_sets_LDADD = \
|
||||
$(top_builddir)/src/auc.o \
|
||||
$(top_builddir)/src/logging.o \
|
||||
$(top_srcdir)/src/auc.c \
|
||||
$(top_srcdir)/src/logging.c \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
@@ -116,14 +116,14 @@ int rand_get(uint8_t *rand, unsigned int len)
|
||||
/* Subscriber with 2G-only (COMP128v1) authentication data */
|
||||
static void test_gen_vectors_2g_only(void)
|
||||
{
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data2){
|
||||
aud2g = (struct osmo_sub_auth_data){
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_COMP128v1,
|
||||
};
|
||||
@@ -131,7 +131,7 @@ static void test_gen_vectors_2g_only(void)
|
||||
osmo_hexparse("EB215756028D60E3275E613320AEC880",
|
||||
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data2){ 0 };
|
||||
aud3g = (struct osmo_sub_auth_data){ 0 };
|
||||
|
||||
next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
|
||||
|
||||
@@ -179,14 +179,14 @@ static void test_gen_vectors_2g_only(void)
|
||||
* reflects the default configuration of sysmoUSIM-SJS1 */
|
||||
static void test_gen_vectors_2g_plus_3g(void)
|
||||
{
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data2){
|
||||
aud2g = (struct osmo_sub_auth_data){
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_COMP128v1,
|
||||
};
|
||||
@@ -194,11 +194,9 @@ static void test_gen_vectors_2g_plus_3g(void)
|
||||
osmo_hexparse("EB215756028D60E3275E613320AEC880",
|
||||
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data2){
|
||||
aud3g = (struct osmo_sub_auth_data){
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
.u.umts.sqn = 31,
|
||||
};
|
||||
|
||||
@@ -294,8 +292,8 @@ void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
|
||||
* tuples are suitable for both 2G and 3G authentication */
|
||||
static void test_gen_vectors_3g_only(void)
|
||||
{
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
struct osmo_auth_vector vecs[3];
|
||||
uint8_t auts[14];
|
||||
@@ -304,13 +302,11 @@ static void test_gen_vectors_3g_only(void)
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data2){ 0 };
|
||||
aud2g = (struct osmo_sub_auth_data){ 0 };
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data2){
|
||||
aud3g = (struct osmo_sub_auth_data){
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
.u.umts.sqn = 31,
|
||||
};
|
||||
|
||||
@@ -470,20 +466,18 @@ static void test_gen_vectors_3g_only(void)
|
||||
* 2G and 3G authentication */
|
||||
static void test_gen_vectors_3g_xor(void)
|
||||
{
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data2){ 0 };
|
||||
aud2g = (struct osmo_sub_auth_data){ 0 };
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data2){
|
||||
aud3g = (struct osmo_sub_auth_data){
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_XOR_3G,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
.algo = OSMO_AUTH_ALG_XOR,
|
||||
.u.umts.sqn = 0,
|
||||
};
|
||||
|
||||
@@ -523,43 +517,39 @@ void test_gen_vectors_bad_args(void)
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
struct osmo_sub_auth_data2 aud2g = {
|
||||
struct osmo_sub_auth_data aud2g = {
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_COMP128v1,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data2 aud3g = {
|
||||
struct osmo_sub_auth_data aud3g = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data2 aud2g_noalg = {
|
||||
struct osmo_sub_auth_data aud2g_noalg = {
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_NONE,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data2 aud3g_noalg = {
|
||||
struct osmo_sub_auth_data aud3g_noalg = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_NONE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data2 aud_notype = {
|
||||
struct osmo_sub_auth_data aud_notype = {
|
||||
.type = OSMO_AUTH_TYPE_NONE,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data2 no_aud = {
|
||||
struct osmo_sub_auth_data no_aud = {
|
||||
.type = OSMO_AUTH_TYPE_NONE,
|
||||
.algo = OSMO_AUTH_ALG_NONE,
|
||||
};
|
||||
|
||||
struct {
|
||||
struct osmo_sub_auth_data2 *aud2g;
|
||||
struct osmo_sub_auth_data2 *aud3g;
|
||||
struct osmo_sub_auth_data *aud2g;
|
||||
struct osmo_sub_auth_data *aud3g;
|
||||
uint8_t *rand_auts;
|
||||
uint8_t *auts;
|
||||
const char *label;
|
||||
|
||||
@@ -24,46 +24,43 @@
|
||||
|
||||
static void {func_name}(void)
|
||||
{{
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data2){{ 0 }};
|
||||
aud2g = (struct osmo_sub_auth_data){{ 0 }};
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data2){{
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
aud3g = (struct osmo_sub_auth_data){{
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.sqn = 31,
|
||||
}};
|
||||
}};
|
||||
|
||||
osmo_hexparse("{Ki}",
|
||||
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
|
||||
osmo_hexparse("{OPc}",
|
||||
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
|
||||
osmo_hexparse("{Ki}",
|
||||
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
|
||||
osmo_hexparse("{OPc}",
|
||||
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
|
||||
|
||||
osmo_hexparse("{RAND}",
|
||||
fake_rand, sizeof(fake_rand));
|
||||
osmo_hexparse("{RAND}",
|
||||
fake_rand, sizeof(fake_rand));
|
||||
|
||||
vec = (struct osmo_auth_vector){{ {{0}} }};
|
||||
vec.res_len = 8;
|
||||
vec = (struct osmo_auth_vector){{ {{0}} }};
|
||||
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
|
||||
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
|
||||
VERBOSE_ASSERT(rc, == 1, "%d");
|
||||
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
|
||||
VERBOSE_ASSERT(rc, == 1, "%d");
|
||||
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
|
||||
|
||||
VEC_IS(&vec,
|
||||
" rand: {RAND}\n"
|
||||
" ck: {MIL3G-CK}\n"
|
||||
" ik: {MIL3G-IK}\n"
|
||||
" res: {MIL3G-RES}0000000000000000\n"
|
||||
" kc: {Kc}\n"
|
||||
" sres: {SRES#1}\n"
|
||||
);
|
||||
VEC_IS(&vec,
|
||||
" rand: {RAND}\n"
|
||||
" ck: {MIL3G-CK}\n"
|
||||
" ik: {MIL3G-IK}\n"
|
||||
" res: {MIL3G-RES}0000000000000000\n"
|
||||
" kc: {Kc}\n"
|
||||
" sres: {SRES#1}\n"
|
||||
);
|
||||
|
||||
comment_end();
|
||||
}}
|
||||
|
||||
@@ -55,7 +55,7 @@ char *vec_str(const struct osmo_auth_vector *vec)
|
||||
if (pos >= end) \
|
||||
return buf; \
|
||||
pos += snprintf(pos, sizeof(buf) - (pos - buf), \
|
||||
" " #what ": %s\n", \
|
||||
" " #what ": %s\n", \
|
||||
osmo_hexdump_nospc((void*)&vec->what, sizeof(vec->what)))
|
||||
|
||||
append(rand);
|
||||
@@ -71,7 +71,7 @@ char *vec_str(const struct osmo_auth_vector *vec)
|
||||
|
||||
#define VEC_IS(vec, expect) do { \
|
||||
char *_is = vec_str(vec); \
|
||||
if (strcmp(_is, expect)) { \
|
||||
if (strcmp(_is, expect)) { \
|
||||
fprintf(stderr, "MISMATCH! expected ==\n%s\n", \
|
||||
expect); \
|
||||
char *a = _is; \
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
AM_CPPFLAGS = \
|
||||
AM_CFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
|
||||
@@ -122,16 +122,16 @@ static void _fill_invalid(void *dest, size_t size)
|
||||
/* Not linking the real auc_compute_vectors(), just returning num_vec.
|
||||
* This gets called by db_get_auc(), but we're only interested in its rc. */
|
||||
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
const uint8_t *rand_auts, const uint8_t *auts)
|
||||
{ return num_vec; }
|
||||
|
||||
static struct db_context *dbc = NULL;
|
||||
static void *ctx = NULL;
|
||||
static struct hlr_subscriber g_subscr;
|
||||
static struct osmo_sub_auth_data2 g_aud2g;
|
||||
static struct osmo_sub_auth_data2 g_aud3g;
|
||||
static struct osmo_sub_auth_data g_aud2g;
|
||||
static struct osmo_sub_auth_data g_aud3g;
|
||||
static int g_rc;
|
||||
static int64_t g_id;
|
||||
|
||||
@@ -180,21 +180,18 @@ void dump_subscr(struct hlr_subscriber *subscr)
|
||||
#undef Pb
|
||||
}
|
||||
|
||||
void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
|
||||
void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
|
||||
{
|
||||
if (aud->type == OSMO_AUTH_TYPE_NONE) {
|
||||
fprintf(stderr, "%s: none\n", label);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: struct osmo_sub_auth_data2 {\n", label);
|
||||
fprintf(stderr, "%s: struct osmo_sub_auth_data {\n", label);
|
||||
#define Pf(name, fmt) \
|
||||
Pfo(name, fmt, aud)
|
||||
#define Phex(name) \
|
||||
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name)))
|
||||
#define Phexl(name, len) \
|
||||
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, aud->len))
|
||||
|
||||
|
||||
Pfv(type, "%s", osmo_sub_auth_type_name(aud->type));
|
||||
Pfv(algo, "%s", osmo_auth_alg_name(aud->algo));
|
||||
@@ -203,9 +200,9 @@ void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
|
||||
Phex(u.gsm.ki);
|
||||
break;
|
||||
case OSMO_AUTH_TYPE_UMTS:
|
||||
Phexl(u.umts.opc, u.umts.opc_len);
|
||||
Phex(u.umts.opc);
|
||||
Pf(u.umts.opc_is_op, "%u");
|
||||
Phexl(u.umts.k, u.umts.k_len);
|
||||
Phex(u.umts.k);
|
||||
Phex(u.umts.amf);
|
||||
if (aud->u.umts.sqn) {
|
||||
Pf(u.umts.sqn, "%"PRIu64);
|
||||
@@ -222,7 +219,6 @@ void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
|
||||
|
||||
#undef Pf
|
||||
#undef Phex
|
||||
#undef Phexl
|
||||
}
|
||||
|
||||
void db_raw_sql(struct db_context *dbc, const char *sql)
|
||||
@@ -590,7 +586,7 @@ static void test_subscr_aud(void)
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
|
||||
0);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
@@ -608,7 +604,7 @@ static void test_subscr_aud(void)
|
||||
-ENOENT);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
|
||||
0);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
@@ -711,12 +707,12 @@ static void test_subscr_aud(void)
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f000000000000f00000000000f000000f00000000")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")),
|
||||
-EINVAL);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "f00")),
|
||||
-EINVAL);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
|
||||
@@ -824,7 +824,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v1,
|
||||
.u.gsm.ki = '0123456789abcdef0123456789abcdef',
|
||||
@@ -841,7 +841,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v1,
|
||||
.u.gsm.ki = '0123456789abcdef0123456789abcdef',
|
||||
@@ -853,7 +853,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v2, "BeadedBe
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v2,
|
||||
.u.gsm.ki = 'beadedbeeaced1ebbeddefacedfacade',
|
||||
@@ -865,21 +865,21 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "DeafBedd
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'deafbeddedbabeacceededfadeddecaf',
|
||||
}
|
||||
3G: none
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = XOR-2G,
|
||||
.algo = XOR,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: none
|
||||
@@ -900,14 +900,14 @@ DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)) --> -ENOENT
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = XOR-2G,
|
||||
.algo = XOR,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: none
|
||||
@@ -932,7 +932,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -954,7 +954,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -970,7 +970,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'deaf0ff1ced0d0dabbedd1ced1cef00d',
|
||||
@@ -985,7 +985,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1001,7 +1001,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
|
||||
@@ -1033,7 +1033,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
|
||||
@@ -1069,12 +1069,12 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_3g(OSMO_AUTH_ALG_MILENAGE, "BeefedCaf
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1097,12 +1097,12 @@ DAUC Cannot update auth tokens: Unknown auth algo: 99999
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1112,17 +1112,17 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
.u.umts.ind_bitlen = 5,
|
||||
}
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f000000000000f00000000000f000000f00000000")) --> -EINVAL
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")) --> -EINVAL
|
||||
DAUC Cannot update auth tokens: Invalid KI: 'f000000000000f00000000000f000000f00000000'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1132,17 +1132,17 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
.u.umts.ind_bitlen = 5,
|
||||
}
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")) --> -EINVAL
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "f00")) --> -EINVAL
|
||||
DAUC Cannot update auth tokens: Invalid KI: 'f00'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1157,12 +1157,12 @@ DAUC Cannot update auth tokens: auth algo not suited for 2G: MILENAGE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1177,12 +1177,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: '0f000000000000f00000000000f0000
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1197,12 +1197,12 @@ DAUC Cannot update auth tokens: Invalid K: '000000000000f00000000000f000000'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1217,12 +1217,12 @@ DAUC Cannot update auth tokens: Invalid ind_bitlen: 29
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1237,12 +1237,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: 'X000000000000f00000000000f00000
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1257,12 +1257,12 @@ DAUC Cannot update auth tokens: Invalid K: 'f000000000000 f00000000000 f000000'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
2G: struct osmo_sub_auth_data {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1338,7 +1338,7 @@ sqlite3_prepare_v2(dbc->db, sql, -1, &stmt, NULL) --> SQLITE_OK
|
||||
sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -ENOKEY
|
||||
DAUC IMSI='123456789000000': Error reading Ki, expected min length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading Ki, expected length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
|
||||
@@ -1359,7 +1359,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
DAUC IMSI='123456789000000': Error reading K, expected min length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading K, expected length 16 but has length 15
|
||||
|
||||
|
||||
|
||||
@@ -1374,7 +1374,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
DAUC IMSI='123456789000000': Error reading OP, expected min length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading OP, expected length 16 but has length 15
|
||||
|
||||
|
||||
|
||||
@@ -1389,7 +1389,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
DAUC IMSI='123456789000000': Error reading OPC, expected min length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading OPC, expected length 16 but has length 15
|
||||
|
||||
|
||||
|
||||
@@ -1458,7 +1458,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1477,7 +1477,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1495,7 +1495,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1513,7 +1513,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1534,7 +1534,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1550,7 +1550,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1568,7 +1568,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1586,7 +1586,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
3G: struct osmo_sub_auth_data {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
|
||||
@@ -43,5 +43,5 @@ OsmoHLR# subscriber imsi 5555555 create
|
||||
MSISDN: none
|
||||
OsmoHLR# subscriber imsi 5555555 update msisdn 55555555555555
|
||||
% Updated subscriber IMSI='5555555' to MSISDN='55555555555555'
|
||||
OsmoHLR# subscriber imsi 5555555 update aud2g xor-2g ki 55555555555555555555555555555555
|
||||
OsmoHLR# subscriber imsi 5555555 update aud2g xor ki 55555555555555555555555555555555
|
||||
OsmoHLR# subscriber imsi 5555555 update aud3g milenage k 55555555555555555555555555555555 opc 55555555555555555555555555555555
|
||||
|
||||
@@ -12,7 +12,7 @@ Table auc_2g contents:
|
||||
algo_id_2g|ki|subscriber_id
|
||||
1|BeefedCafeFaceAcedAddedDecadeFee|1
|
||||
2|33333333333333333333333333333333|4
|
||||
6|55555555555555555555555555555555|6
|
||||
4|55555555555555555555555555555555|6
|
||||
|
||||
Table: auc_3g
|
||||
name|type|notnull|dflt_value|pk
|
||||
@@ -86,7 +86,6 @@ DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 3
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 4
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 5
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 6
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 7
|
||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
||||
|
||||
Resulting db:
|
||||
@@ -101,15 +100,15 @@ Table auc_2g contents:
|
||||
algo_id_2g|ki|subscriber_id
|
||||
1|BeefedCafeFaceAcedAddedDecadeFee|1
|
||||
2|33333333333333333333333333333333|4
|
||||
6|55555555555555555555555555555555|6
|
||||
4|55555555555555555555555555555555|6
|
||||
|
||||
Table: auc_3g
|
||||
name|type|notnull|dflt_value|pk
|
||||
algo_id_3g|INTEGER|1||0
|
||||
ind_bitlen|INTEGER|1|5|0
|
||||
k|VARCHAR(64)|1||0
|
||||
op|VARCHAR(64)|0||0
|
||||
opc|VARCHAR(64)|0||0
|
||||
k|VARCHAR(32)|1||0
|
||||
op|VARCHAR(32)|0||0
|
||||
opc|VARCHAR(32)|0||0
|
||||
sqn|INTEGER|1|0|0
|
||||
subscriber_id|INTEGER|0||1
|
||||
|
||||
@@ -180,5 +179,5 @@ osmo-hlr --database $db --db-check --config-file $srcdir/osmo-hlr.cfg
|
||||
rc = 0
|
||||
DMAIN hlr starting
|
||||
DDB using database: <PATH>test.db
|
||||
DDB Database <PATH>test.db' has HLR DB schema version 7
|
||||
DDB Database <PATH>test.db' has HLR DB schema version 6
|
||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
||||
|
||||
@@ -61,7 +61,7 @@ CREATE TABLE auc_2g (
|
||||
);
|
||||
INSERT INTO auc_2g VALUES(1,1,'BeefedCafeFaceAcedAddedDecadeFee');
|
||||
INSERT INTO auc_2g VALUES(4,2,'33333333333333333333333333333333');
|
||||
INSERT INTO auc_2g VALUES(6,6,'55555555555555555555555555555555');
|
||||
INSERT INTO auc_2g VALUES(6,4,'55555555555555555555555555555555');
|
||||
CREATE TABLE auc_3g (
|
||||
subscriber_id INTEGER PRIMARY KEY, -- subscriber.id
|
||||
algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(LIBOSMOABIS_CFLAGS) \
|
||||
|
||||
@@ -53,7 +53,6 @@ OsmoHLR(config-hlr)# ?
|
||||
OsmoHLR(config-hlr)# list
|
||||
...
|
||||
gsup
|
||||
ps
|
||||
database PATH
|
||||
euse NAME
|
||||
no euse NAME
|
||||
@@ -113,12 +112,6 @@ hlr
|
||||
ipa-name unnamed-HLR
|
||||
ussd route prefix *#100# internal own-msisdn
|
||||
ussd route prefix *#101# internal own-imsi
|
||||
ps
|
||||
pdp-profiles default
|
||||
profile 1
|
||||
apn internet
|
||||
profile 2
|
||||
apn *
|
||||
end
|
||||
|
||||
OsmoHLR# configure terminal
|
||||
@@ -455,44 +448,3 @@ mslookup
|
||||
client
|
||||
mdns bind 239.192.23.42 4266
|
||||
...
|
||||
OsmoHLR(config-mslookup-server)# end
|
||||
OsmoHLR# configure terminal
|
||||
|
||||
OsmoHLR(config)# hlr
|
||||
OsmoHLR(config-hlr)# ps?
|
||||
ps Configure the PS options
|
||||
|
||||
OsmoHLR(config-hlr)# ps
|
||||
|
||||
OsmoHLR(config-hlr-ps)# list
|
||||
...
|
||||
pdp-profiles default
|
||||
no pdp-profiles default
|
||||
...
|
||||
OsmoHLR(config-hlr-ps)# no pdp-profiles default
|
||||
|
||||
|
||||
OsmoHLR(config-hlr-ps)# pdp-profiles default
|
||||
OsmoHLR(config-hlr-ps-pdp-profiles)# ?
|
||||
...
|
||||
profile Configure a PDP profile
|
||||
...
|
||||
OsmoHLR(config-hlr-ps-pdp-profiles)# profile 1
|
||||
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# ?
|
||||
...
|
||||
apn Configure the APN.
|
||||
...
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# apn internet
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# exit
|
||||
OsmoHLR(config-hlr-ps-pdp-profiles)# profile 2
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# apn *
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# show running-config
|
||||
...
|
||||
ps
|
||||
pdp-profiles default
|
||||
profile 1
|
||||
apn internet
|
||||
profile 2
|
||||
apn *
|
||||
...
|
||||
|
||||
@@ -674,12 +674,9 @@ lmsi 00000000
|
||||
GET 112 subscriber.by-imsi-901991234567891.aud2g
|
||||
GET_REPLY 112 subscriber.by-imsi-901991234567891.aud2g none
|
||||
|
||||
SET 113 subscriber.by-imsi-901991234567891.aud2g xor-2g,c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
SET 113 subscriber.by-imsi-901991234567891.aud2g xor,c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
SET_REPLY 113 subscriber.by-imsi-901991234567891.aud2g OK
|
||||
|
||||
GET 114 subscriber.by-imsi-901991234567891.aud2g
|
||||
GET_REPLY 114 subscriber.by-imsi-901991234567891.aud2g XOR-2G,c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
|
||||
SET 115 subscriber.by-imsi-901991234567891.aud2g none
|
||||
SET_REPLY 115 subscriber.by-imsi-901991234567891.aud2g OK
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ OsmoHLR# list
|
||||
subscriber (imsi|msisdn|id|imei) IDENT delete
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update msisdn (none|MSISDN)
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud2g none
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor-2g) ki KI
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor) ki KI
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud3g none
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud3g (milenage|tuak) k K (op|opc) OP_C [ind-bitlen] [<0-28>]
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud3g xor-3g k K [ind-bitlen] [<0-28>]
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud3g milenage k K (op|opc) OP_C [ind-bitlen] [<0-28>]
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud3g xor k K [ind-bitlen] [<0-28>]
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update imei (none|IMEI)
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update network-access-mode (none|cs|ps|cs+ps)
|
||||
show mslookup services
|
||||
@@ -144,7 +144,7 @@ OsmoHLR# subscriber imsi 123456789023000 update aud2g ?
|
||||
comp128v1 Use COMP128v1 algorithm
|
||||
comp128v2 Use COMP128v2 algorithm
|
||||
comp128v3 Use COMP128v3 algorithm
|
||||
xor-2g Use XOR-2G algorithm
|
||||
xor Use XOR algorithm
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ?
|
||||
ki Set Ki Encryption Key
|
||||
@@ -155,12 +155,12 @@ OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki ?
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki val ?
|
||||
<cr>
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g xor-2g ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g xor ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d
|
||||
OsmoHLR# subscriber imsi 123456789023000 show
|
||||
ID: 101
|
||||
IMSI: 123456789023000
|
||||
MSISDN: 423
|
||||
2G auth: XOR-2G
|
||||
...
|
||||
KI=deaf0ff1ced0d0dabbedd1ced1cef00d
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee
|
||||
@@ -241,7 +241,7 @@ OsmoHLR# subscriber id 101 show
|
||||
2G auth: COMP128v3
|
||||
KI=c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
|
||||
OsmoHLR# subscriber id 101 update aud2g xor-2g ki CoiffedCicadaeAcidifiedAcaciaBoa
|
||||
OsmoHLR# subscriber id 101 update aud2g xor ki CoiffedCicadaeAcidifiedAcaciaBoa
|
||||
% Invalid value for KI: 'CoiffedCicadaeAcidifiedAcaciaBoa'
|
||||
OsmoHLR# subscriber id 101 show
|
||||
ID: 101
|
||||
@@ -250,7 +250,7 @@ OsmoHLR# subscriber id 101 show
|
||||
2G auth: COMP128v3
|
||||
KI=c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
|
||||
OsmoHLR# subscriber id 101 update aud2g xor-2g ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX
|
||||
OsmoHLR# subscriber id 101 update aud2g xor ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX
|
||||
% Invalid value for KI: 'C01ffedC1cadaeAc1d1f1edAcac1aB0aX'
|
||||
OsmoHLR# subscriber id 101 show
|
||||
ID: 101
|
||||
@@ -269,21 +269,20 @@ OsmoHLR# subscriber id 101 show
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g ?
|
||||
none Delete 3G authentication data
|
||||
milenage Use Milenage algorithm
|
||||
tuak Use TUAK algorithm
|
||||
xor-3g Use XOR-3G algorithm
|
||||
xor Use XOR algorithm
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage ?
|
||||
k Set Encryption Key K
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k ?
|
||||
K K as 32/64 hexadecimal characters
|
||||
K K as 32 hexadecimal characters
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d ?
|
||||
op Set OP key
|
||||
opc Set OPC key
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc ?
|
||||
OP_C OP or OPC as 32/64 hexadecimal characters
|
||||
OP_C OP or OPC as 32 hexadecimal characters
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc CededEffacedAceFacedBadFadedBeef ?
|
||||
[ind-bitlen] Set IND bit length
|
||||
|
||||
@@ -130,7 +130,7 @@ ERROR 54 Value failed verification.
|
||||
SET 55 subscriber.by-imsi-901990000000003.aud2g foobar,2134
|
||||
ERROR 55 Unknown auth algorithm.
|
||||
|
||||
SET 56 subscriber.by-imsi-901990000000003.aud2g xor-2g,2134
|
||||
SET 56 subscriber.by-imsi-901990000000003.aud2g xor,2134
|
||||
ERROR 56 Invalid KI.
|
||||
|
||||
SET 57 subscriber.by-imsi-901990000000003.aud3g foobar
|
||||
@@ -139,17 +139,17 @@ ERROR 57 Value failed verification.
|
||||
SET 58 subscriber.by-imsi-901990000000003.aud3g foobar,2134
|
||||
ERROR 58 Unknown auth algorithm.
|
||||
|
||||
SET 59 subscriber.by-imsi-901990000000003.aud3g milenage,2134
|
||||
ERROR 59 Invalid KI.
|
||||
SET 60 subscriber.by-imsi-901990000000003.aud3g milenage,2134
|
||||
ERROR 60 Invalid KI.
|
||||
|
||||
SET 60 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA
|
||||
ERROR 60 Invalid format.
|
||||
|
||||
SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
|
||||
SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA
|
||||
ERROR 61 Invalid format.
|
||||
|
||||
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz
|
||||
ERROR 62 Invalid OP/OPC.
|
||||
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
|
||||
ERROR 62 Invalid format.
|
||||
|
||||
SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,
|
||||
ERROR 63 Invalid format.
|
||||
SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz
|
||||
ERROR 63 Invalid OP/OPC.
|
||||
|
||||
SET 64 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,
|
||||
ERROR 64 Invalid format.
|
||||
|
||||
@@ -27,7 +27,12 @@ AT_KEYWORDS([db])
|
||||
cat $abs_srcdir/db/db_test.ok > expout
|
||||
cat $abs_srcdir/db/db_test.err > experr
|
||||
sqlite3 db_test.db < $abs_top_srcdir/sql/hlr.sql
|
||||
AT_CHECK([$abs_top_builddir/tests/db/db_test], [], [expout], [experr])
|
||||
|
||||
# Compatibility with libosmocore I446e54d0ddf4a18c46ee022b1249af73552e3ce1
|
||||
$abs_top_builddir/tests/db/db_test >out 2>err
|
||||
sed -i "s/XOR-3G,/XOR,/g" err
|
||||
|
||||
AT_CHECK([cat out; cat err >&2], [], [expout], [experr])
|
||||
AT_CLEANUP
|
||||
|
||||
# AT_SKIP_IF: disable for old sqlite versions, because the way we dump tables in the test doesn't work with it.
|
||||
|
||||
Reference in New Issue
Block a user