Compare commits

...

41 Commits
1.5.1 ... 1.7.0

Author SHA1 Message Date
Pau Espin Pedrol
d052f076e3 Bump version: 1.6.0.20-37f0-dirty → 1.7.0
Change-Id: I3f169ff8f9b10a4d4b5c50286951d326fa713245
2023-09-12 14:41:34 +02:00
Alexander Couzens
37f0b3a8f3 Add support for multiple APN profiles for subscriber data
Previously the HLR sent in the Insert Subscriber Data call only the
wildcard APN as a single entry.
This violates the spec because the first entry (with the lowest context_id) is
always the default APN, but it is forbidden to have a wildcard APN as default apn.

Introduce a default template/profile which can contain multiple APNs.
This profile is always sent out to the SGSN/MME as part of Insert-Subscriber-Data.
In the future a subscriber might have a profile template name written into the
database which will resolve to a "pdp-profile premium" in the configuration.

To be backward compatible, if the pdp-profile default section is missing,
the HLR will send out only a wildcard APN.

Config example:

hlr
 ps
  pdp-profile default
   profile 1
    apn internet
   profile 2
    apn *

Changes to the apn list will be only handed out to subscribers
when the subscriber do a location update.

Related: SYS#6391
Change-Id: I540132ee5dcfd09f4816e02e702927e1074ca50f
2023-09-12 09:48:02 +00:00
Harald Welte
7a763aa012 Add VTY support for TUAK algorithm
Change-Id: If2611658f7cb990b484d7429ab2f944f56fd2eb6
Depends: libosmocore.git Ib905b8d8bdf248e8299bf50666ee1bca8298433d
2023-08-29 13:42:41 +00:00
Harald Welte
626f5eb740 db: extend database schema to support 256bit K and/or OP[c] values
Other UMTS AKA algorithms than MILENAGE (notably TUAK) support K sizes
of up to 256bit, or mandate a OP/OPc size of 256 bit.

Let's extend our database schema to accommodate such larger sizes.

Change-Id: Ibbde68484c904507a15c35cbfdf88cd47d0c7039
2023-08-29 13:42:41 +00:00
Vadim Yanitskiy
5800f3add5 USSD: fix handling of ussd-DataCodingScheme != 0x0f
The usual Data Coding Scheme value in the mobile-originated USSD
request (processUnstructuredSS-Request) is 0x0f, which means:

  0000 .... = Coding Group: Coding Group 0 (Language using the GSM 7 bit default alphabet)
  .... 1111 = Language: unspecified

However some modems are known to use a different default value, if
not specified explicitly (AT+CUSD has optional DCS parameter):

  0000 .... = Coding Group: Coding Group 0 (Language using the GSM 7 bit default alphabet)
  .... 0000 = Language: German (0)

In function rx_proc_ss_req(), we should not be using req.ussd_text,
because this field has been deprecated and may contain unexpected
data.  For example, in the abovementioned case it would contain the
7 bit encoded ussd-String 'aa510c061b01'O and osmo-hlr would indeed
fail to find a matching route for a non-ASCII string.

Instead of relaying on gsm0480_parse_facility_ie(), let's check the
Data Coding Scheme value and decode the request string ourselves.
Expect the Coding Group 0, but be more tolerant to the indicated
language: print a warning and treat it as '1111'B (unspecified).

Change-Id: Ib7bac660b1a7942adcfbe7b14f162c95061a25db
Related: OS#6075
2023-07-21 12:49:20 +00:00
Vadim Yanitskiy
f8b73f0682 gsup_server: fix msgb memleak in osmo_gsup_server_read_cb()
I noticed that inability to send IPA PONG in response to IPA PING
from osmo-{msc,sgsn} results in an "IPA Multiplex" chunk being leaked.

No matter what's returned from ipa_server_conn_ccm(), we need to free
the msgb containing the incoming IPA message.

Change-Id: I5c5acbffc2913f78db4894ae3633b5eca9c2e8d6
2023-07-05 01:10:43 +07:00
Vadim Yanitskiy
f4223f5b53 ussd: fix GSUP memleaks in rx_proc_ss_{req,error}()
Also take a chance to use a more suitable error cause value.

Change-Id: I22ba5ad470989b7e8ba8fe2be170eac4adcb48c5
2023-07-05 00:24:19 +07:00
Vadim Yanitskiy
1c23f304d1 lu_fsm: fix memleak in lu_fsm_wait_insert_data_result()
Currently osmo-hlr leaks memory (msgb holding 1203 bytes of data and
a struct osmo_gsup_req) on receipt of OSMO_GSUP_MSGT_INSERT_DATA_ERROR.

Change-Id: I4c70a06169158c869360707a7a62436dbf13b9b3
2023-07-05 00:15:17 +07:00
Harald Welte
f4159bd54c src/db.c: Switch from "const char *statements" to "const char * const"
This is primarily to make the linter happy, which spews "static const
char * array should probably be static const char * const" errors in
gerrit when adding similar new code to this existing file.  So let's
first convert the old code and then add new code that makes the linter
happy.  I guess it does have a point, as both the individual string
pointers as well as the array of the pointers are constant.

Change-Id: I39e9fb6bd8052f4878cfc95061775bf940631ae5
2023-06-14 14:53:07 +02:00
Harald Welte
a854b48762 Port to new libosmogsm 'struct osmo_sub_auth_data2'
libosmogsm has recently introdcued a 'struct osmo_sub_auth_data2' as
successor to 'struct osmo_sub_auth_data', together with updated
osmo_auth_gen_vec2/osmo_auth_gen_vec_auts2 API.

The rationale of this new API is to enable
* support for AKA algorithms which use K and/or OP[c] values of 256bit
  (instead of the classic 128bit)
* support for RES length sizes of 4 and 16 bytes (instead of the classic
  8 bytes)

This commit just jumps over to the new API without adding any related
functionality to osmo-hlr.  The latter is left for subsequent commits.

Change-Id: I3207c7bfb73e9ff5471e5c26b66639549e4d48a2
Depends: libosmocore.git Ie775fedba4a3fa12314c0f7c8a369662ef6a40df
2023-06-14 14:53:04 +02:00
Harald Welte
91150802f8 cosmetic: gen_ts_55_205_test_sets/main_template tabs istead of spaces
Let's consistently use our normal tab indent style

Change-Id: I4172b59131ac4166174c1860fcb07b7bee3df728
2023-06-03 19:32:44 +02:00
Harald Welte
8f3fa656e7 cosmetic: gen_ts_55_205_test_sets/func_template.c: Use tab-indent
This templates is used for generating C code, so it should use our
normal tab-based code indenting.

Change-Id: I0be7eb2d7b551d7eaaee15994ef37262694819f6
2023-06-03 19:29:46 +02:00
Harald Welte
829713a69d Introduce support for XOR-2G algorithm
So far we supported a "xor" algorithm in osmo-hlr, without specifying
whether it's the XOR-3G or the (different) XOR-2G algorithm.

Furthermore, it was buggy in the sense that it permitted the XOR[-3G]
for 2G authentication data in the database.

This patch
* renames existing "xor" to "xor-3g"
* disallows "xor-3g" usage with 2G authentication data
* introduces support for XOR-2G as "xor-2g" in the VTY

Change-Id: I039a1f84fda54a908a82fe621e7fd078cb85e4c6
Depends: libosmocore.git I0ee0565382c1e4515d44ff9b1752685c0a66ae39
2023-05-30 21:43:14 +02:00
Oliver Smith
5edf387353 systemd: depend on networking-online.target
Related: SYS#6400
Change-Id: I29e547242b2ed1cfc4750c7d7e5f8636c2e8f3dc
2023-05-26 14:10:45 +02:00
Alexander Couzens
2989873a68 hlr: use talloc for memory allocation in osmo_gsup_create_insert_subscriber_data_msg
Don't use static buffers for APN and MSISDN.
When encoding multiple APNs the static buffer might be too small.
In prepration to support multiple APNs in subscriber data

Change-Id: I00b5c2dfadcf6e0740e93b4c3292d2654d22e80c
2023-05-10 07:58:57 +00:00
Oliver Smith
390f6fcf13 debian: set compat level to 10
Related: OS#5958
Change-Id: I5d26ab03aacf3b8ef8c1c4c669c12090fd0b7899
2023-04-25 16:48:22 +02:00
Vadim Yanitskiy
d10c2ef366 tests/*/Makefile.am: move -I to AM_CPPFLAGS
Change-Id: I654053e11b0cc824c198f68e4ff0a0fcb295efb0
2023-03-14 20:11:45 +00:00
Vadim Yanitskiy
974aed9c04 tests/auc/Makefile.am: put object files to LDADD
Change-Id: Iaefcfe7a8904841a29094fe40eb5850912544b4c
2023-03-14 20:11:45 +00:00
Pau Espin Pedrol
cf535dbcbd mslookup: Call osmo_fd_unregister() before closing and changing bfd->fd
Change-Id: I26bba0dd092ad5fd6b4959b173fae93b542a93f1
2023-03-14 11:42:24 +01:00
Oliver Smith
a55e63b087 tests/db/db_test.err: adjust to XOR-3G rename
Adjust the test to the related libosmocore change.

Related: libosmocore I446e54d0ddf4a18c46ee022b1249af73552e3ce1
Change-Id: I68878d24340659f888e5e348b937161cffbd54e2
2023-02-22 16:58:57 +01:00
Oliver Smith
62e5c1b2c7 Run struct_endianness.py
Ensure there is no diff to prepare to run this in CI.

Related: OS#5884
Change-Id: I4294a18871214b70cef267fcaaaaada42cb61bf9
2023-02-20 10:48:57 +01:00
Pau Espin Pedrol
ed939154f8 Bump version: 1.5.0.19-268a-dirty → 1.6.0
Change-Id: Ide480a902bbfadefa396f3a0cb925f5dceab4f9c
2023-02-07 16:49:15 +01:00
Alexander Couzens
268a33e58b Add vty reject-cause to set the reject cause
Allow to set the LU reject cause independently for both of the
following cases; either when an IMSI is unknown to the HLR or
when the mslookup client does not a receive a timely response
to a GSUP request for the remote home HLR.

Original patchset modified by <keith@rhizomatica.org>

Change-Id: Icea39020c23fbbea9e92847df76af8986fdbf48a
2023-01-20 14:03:01 +00:00
Neels Hofmeyr
8804a2335a fix memleak of proxy_subscr_listentry
Patch-by: whytek
Related: OS#5854
Change-Id: Ic1ec4911fa5ae91cc75aa865c8201edd83af41ed
2023-01-15 22:45:31 +01:00
Keith
c27bc90ae6 Vty: Fixup config shown/written from vty
This commit fixes the following errors:
Missing timeout param for mslookup.
Fails to start reading a written config if an msc node
is configured in the mslookup server.
Places the individual msc node services in the
top-level wildcard node due to incorrect indentation.

* Add missing timeout param.
* Add missing "ipa-name" part to mslookup-server-msc section.
* Add one extra space indentation for msc services.

This commit also adds a DEFINE for the default timeout value.

Change-Id: Ibb60e74a0803f05f37ac13ca529d77b4cb736025
2022-12-27 17:03:08 +00:00
Oliver Smith
f80ab768d0 osmo_mdns_rfc_record/question_encode: remove ctx
Remove the ctx argument to both functions, as it's not used anymore.

Related: OS#5821
Change-Id: I5e3dd18bf08f7aa42f49c262e13250778ea0c6a2
2022-12-23 13:51:28 +01:00
Oliver Smith
5decd49713 mslookup: use apn functions from libosmocore
Use the apn functions from libosmocore to encode and decode qnames to
avoid code duplication and to avoid unnecessary dynamic allocation.

The unit tests for encoding and decoding rfc_question / rfc_record are
still passing and have the same output.

Fixes: OS#5821
Change-Id: I09d3c617fd6eb4075084ee106d3f3c5803861d2f
2022-12-23 13:51:22 +01:00
Oliver Smith
c5f034b13d osmo_mdns_rfc_record_decode: proper free on err
Free the whole talloc tree of ret if we can't allocate memory for
ret->rdata.

Related: OS#5821
Change-Id: Iefc89e3c75a4bf4ffee3871c7b551a2a608f7d5f
2022-12-23 13:38:19 +01:00
Oliver Smith
01155eaee6 osmo_mdns_rfc_record_decode: check ret of talloc
Related: OS#5821
Change-Id: Icd0f54a8eb80ca50976f248e017f6e5c727385f3
2022-12-23 13:38:15 +01:00
arehbein
e4143234c8 osmo-hlr: Transition to use of 'telnet_init_default'
Related: OS#5809
Change-Id: I5cee719a9c4437712915f0f9760d606f6ec2dd43
2022-12-23 11:13:19 +00:00
Max
6263cf350a ctrl: take both address and port from vty config
Change-Id: Iecae15333a4e77b38d9bce8c8e591af3d5fcf347
2022-12-17 20:59:00 +03:00
Harald Welte
63eefabdde Add -Werror=implicit-int -Werror=int-conversion -Werror=old-style-definition
... if --enable-werror is used

Change-Id: Id465254bf12eb84acb116c86711a5b52b4d3ad35
2022-11-03 12:56:24 +01:00
Harald Welte
7a4765325d Support building with -Werror=strict-prototypes / -Werror=old-style-definition
Unfortunately "-std=c99" is not sufficient to make gcc ignore code that
uses constructs of earlier C standards, which were abandoned in C99.

See https://lwn.net/ml/fedora-devel/Y1kvF35WozzGBpc8@redhat.com/ for
some related discussion.

Change-Id: I861be39275b40c522c02f553074c5a4489e87127
2022-11-03 12:56:24 +01:00
Max
53f6067e97 hlr_vty.c: fix typo
Change-Id: If79ebd9a8998e64be55e52af43e426f37e3972af
2022-09-24 01:55:46 +00:00
Max
8023d246f2 Debian: install osmo-hlr-dgsm.cfg as example config
Related: OS#4107
Change-Id: Ia64f14ada006acb31c5f725dfa0d52f482d3e8b4
2022-09-18 20:19:42 +07:00
Max
00aea9e0d9 systemd: enable basic hardening
This ensures that systemd will not allow us to modify
/home, /root and /run/user which we shouldn't be doing anyway.
See https://www.freedesktop.org/software/systemd/man/systemd.exec.html
for details.

It should also should silence corresponding lintian warning.

Related: OS#4107
Change-Id: Ida5f13bdb9e5bd956c440a381d94eecc18f0b2ef
2022-09-18 19:23:52 +07:00
Max
023c6524a2 Debian: reformat package description
Shorten the lines of package description to comply with
Debian Policy Manual section 3.4.1

Related: OS#4107
Change-Id: Id6bbfc0b013f0e8da80af76206d3ac7fd6b6b0d4
2022-09-18 19:23:52 +07:00
Max
1d02b51a68 Debian: bump copyright year to match current
Related: OS#4107
Change-Id: I581e62b5410a9dddc6b5fd974081d633cc20416d
2022-09-18 19:23:23 +07:00
Max
78a9f92fda Ignore .deb build byproducts
Change-Id: Id36f55cd55be25f764c2b9515eff84d106bab1dc
2022-09-09 22:08:35 +07:00
Max
ad8866e86e Set working directory in systemd service file
By default systemd will execute service with root directory (or home directory for user instance) which might result in
attempts to create files in unexpected place. Let's set it to 'osmocom' subdir of state directory (/var/lib for system
instance) instead.

Related: OS#4821
Change-Id: I40b5d50470cb55ca94af5e17f21658181a02d4c2
2022-08-29 19:45:03 +07:00
Vadim Yanitskiy
6156950634 db_auc: hexparse_stmt(): check value returned by osmo_hexparse()
Change-Id: I78bb3aff9dd57a38278bb34113ea764e0a54c439
Fixes: CID#272997
2022-06-29 11:30:12 +00:00
62 changed files with 1060 additions and 750 deletions

16
.gitignore vendored
View File

@@ -70,3 +70,19 @@ doc/manuals/common
doc/manuals/build
contrib/osmo-hlr.spec
/debian/.debhelper/
/debian/libosmo-gsup-client-dev/
/debian/files
/debian/autoreconf.after
/debian/autoreconf.before
/debian/libosmo-gsup-client0/
/debian/libosmo-mslookup0/
/debian/osmo-hlr-dbg/
/debian/tmp/
/doc/manuals/vty/hlr_vty_reference.xml
/debian/libosmo-mslookup-dev/
/debian/osmo-hlr-doc/
/debian/osmo-hlr/
/debian/osmo-mslookup-utils/
/debian/*.log
/debian/*.substvars

View File

@@ -41,11 +41,11 @@ PKG_PROG_PKG_CONFIG([0.20])
PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1])
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.3.0)
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(SQLITE3, sqlite3)
@@ -93,6 +93,7 @@ AC_ARG_ENABLE(werror,
if test x"$werror" = x"yes"
then
WERROR_FLAGS="-Werror"
WERROR_FLAGS+=" -Werror=implicit-int -Werror=int-conversion -Werror=old-style-definition"
WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
CFLAGS="$CFLAGS $WERROR_FLAGS"

View File

@@ -29,11 +29,11 @@ BuildRequires: python3
%if 0%{?suse_version}
BuildRequires: systemd-rpm-macros
%endif
BuildRequires: pkgconfig(libosmoabis) >= 1.3.0
BuildRequires: pkgconfig(libosmocore) >= 1.7.0
BuildRequires: pkgconfig(libosmoctrl) >= 1.7.0
BuildRequires: pkgconfig(libosmogsm) >= 1.7.0
BuildRequires: pkgconfig(libosmovty) >= 1.7.0
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(sqlite3)
BuildRequires: pkgconfig(talloc) >= 2.0.1
# only needed for populate_hlr_db.pl
@@ -75,19 +75,19 @@ and External USSD Entities (EUSEs) using this library to implement clients.
This subpackage contains libraries and header files for developing
applications that want to make use of libosmo-gsup-client.
%package -n libosmo-mslookup0
%package -n libosmo-mslookup1
Summary: Osmocom MS lookup library
License: GPL-2.0-or-later
Group: System/Libraries
%description -n libosmo-mslookup0
%description -n libosmo-mslookup1
This shared library contains routines for looking up mobile subscribers.
%package -n libosmo-mslookup-devel
Summary: Development files for the Osmocom MS lookup library
License: GPL-2.0-or-later
Group: Development/Libraries/C and C++
Requires: libosmo-mslookup0 = %{version}
Requires: libosmo-mslookup1 = %{version}
%description -n libosmo-mslookup-devel
This shared library contains routines for looking up mobile subscribers.
@@ -146,8 +146,8 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%post -n libosmo-gsup-client0 -p /sbin/ldconfig
%postun -n libosmo-gsup-client0 -p /sbin/ldconfig
%post -n libosmo-mslookup0 -p /sbin/ldconfig
%postun -n libosmo-mslookup0 -p /sbin/ldconfig
%post -n libosmo-mslookup1 -p /sbin/ldconfig
%postun -n libosmo-mslookup1 -p /sbin/ldconfig
%files
%license COPYING
@@ -179,8 +179,8 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%{_libdir}/libosmo-gsup-client.so
%{_libdir}/pkgconfig/libosmo-gsup-client.pc
%files -n libosmo-mslookup0
%{_libdir}/libosmo-mslookup.so.0*
%files -n libosmo-mslookup1
%{_libdir}/libosmo-mslookup.so.1*
%files -n libosmo-mslookup-devel
%dir %{_includedir}/osmocom

View File

@@ -1,12 +1,17 @@
[Unit]
Description=Osmocom Home Location Register (OsmoHLR)
Documentation=https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
Restart=always
StateDirectory=osmocom
WorkingDirectory=%S/osmocom
ExecStart=/usr/bin/osmo-hlr -c /etc/osmocom/osmo-hlr.cfg -l /var/lib/osmocom/hlr.db
RestartSec=2
ProtectHome=true
[Install]
WantedBy=multi-user.target

73
debian/changelog vendored
View File

@@ -1,3 +1,76 @@
osmo-hlr (1.7.0) 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
[ 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
[ 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
[ 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
osmo-hlr (1.6.0) unstable; urgency=medium
[ Vadim Yanitskiy ]
* db_auc: hexparse_stmt(): check value returned by osmo_hexparse()
[ Max ]
* Set working directory in systemd service file
* Ignore .deb build byproducts
* Debian: bump copyright year to match current
* Debian: reformat package description
* systemd: enable basic hardening
* Debian: install osmo-hlr-dgsm.cfg as example config
* hlr_vty.c: fix typo
* ctrl: take both address and port from vty config
[ Harald Welte ]
* Support building with -Werror=strict-prototypes / -Werror=old-style-definition
* Add -Werror=implicit-int -Werror=int-conversion -Werror=old-style-definition
[ arehbein ]
* osmo-hlr: Transition to use of 'telnet_init_default'
[ Oliver Smith ]
* osmo_mdns_rfc_record_decode: check ret of talloc
* osmo_mdns_rfc_record_decode: proper free on err
* mslookup: use apn functions from libosmocore
* osmo_mdns_rfc_record/question_encode: remove ctx
[ Keith ]
* Vty: Fixup config shown/written from vty
[ Neels Hofmeyr ]
* fix memleak of proxy_subscr_listentry
[ Alexander Couzens ]
* Add vty `reject-cause` to set the reject cause
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 07 Feb 2023 16:49:14 +0100
osmo-hlr (1.5.0) unstable; urgency=medium
[ Oliver Smith ]

2
debian/compat vendored
View File

@@ -1 +1 @@
9
10

21
debian/control vendored
View File

@@ -2,17 +2,17 @@ Source: osmo-hlr
Section: net
Priority: optional
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Build-Depends: debhelper (>= 9),
Build-Depends: debhelper (>= 10),
pkg-config,
dh-autoreconf,
autotools-dev,
python3-minimal,
libosmocore-dev (>= 1.7.0),
libosmo-abis-dev (>= 1.3.0),
libosmo-netif-dev (>= 1.2.0),
libosmocore-dev (>= 1.9.0),
libosmo-abis-dev (>= 1.5.0),
libosmo-netif-dev (>= 1.4.0),
libsqlite3-dev,
sqlite3,
osmo-gsm-manuals-dev (>= 1.3.0)
osmo-gsm-manuals-dev (>= 1.5.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
@@ -22,8 +22,9 @@ Package: osmo-hlr
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Osmocom Home Location Register
OsmoHLR is a Osmocom implementation of HLR (Home Location Registrar) which works over GSUP
protocol. The subscribers are store in sqlite DB. It supports both 2G and 3G authentication.
OsmoHLR is a Osmocom implementation of HLR (Home Location Registrar) which
works over GSUP protocol. The subscribers are store in sqlite DB.
It supports both 2G and 3G authentication.
Package: osmo-hlr-dbg
Architecture: any
@@ -58,7 +59,7 @@ Description: Development headers of Osmocom GSUP client library
.
This package contains the development headers.
Package: libosmo-mslookup0
Package: libosmo-mslookup1
Section: libs
Architecture: any
Multi-Arch: same
@@ -72,7 +73,7 @@ Package: libosmo-mslookup-dev
Architecture: any
Multi-Arch: same
Depends: ${misc:Depends},
libosmo-mslookup0 (= ${binary:Version}),
libosmo-mslookup1 (= ${binary:Version}),
libosmocore-dev
Pre-Depends: ${misc:Pre-Depends}
Description: Development headers of Osmocom MS lookup library
@@ -84,7 +85,7 @@ Package: osmo-mslookup-utils
Architecture: any
Section: utils
Depends: ${shlibs:Depends},
libosmo-mslookup0 (= ${binary:Version}),
libosmo-mslookup1 (= ${binary:Version}),
${misc:Depends}
Multi-Arch: same
Description: Utilities for Osmocom MS lookup

2
debian/copyright vendored
View File

@@ -3,7 +3,7 @@ Upstream-Name: OsmoHLR
Source: http://cgit.osmocom.org/osmo-hlr/
Files: *
Copyright: 2016-2017 Sysmocom s. f. m. c. GmbH <info@sysmocom.de>
Copyright: 2016-2022 Sysmocom s. f. m. c. GmbH <info@sysmocom.de>
License: AGPL-3+
License: AGPL-3+

View File

@@ -5,5 +5,5 @@
/usr/share/doc/osmo-hlr/sql/hlr.sql
/usr/share/doc/osmo-hlr/sql/hlr_data.sql
/usr/share/doc/osmo-hlr/examples/osmo-hlr.cfg
/usr/share/doc/osmo-hlr/examples/osmo-hlr-dgsm.cfg
/usr/share/osmocom/osmo-hlr-post-upgrade.sh
/var/lib/osmocom

View File

@@ -24,3 +24,9 @@ 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 *

View File

@@ -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_data *aud2g,
struct osmo_sub_auth_data *aud3g,
struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data2 *aud3g,
const uint8_t *rand_auts, const uint8_t *auts);

View File

@@ -70,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_data *aud2g,
struct osmo_sub_auth_data *aud3g,
struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data2 *aud3g,
int64_t *subscr_id);
int db_update_sqn(struct db_context *dbc, int64_t id,
@@ -121,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_data, but the keys are in hexdump representation.
/* Like struct osmo_sub_auth_data2, 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,

View File

@@ -25,6 +25,7 @@
#include <osmocom/gsupclient/cni_peer_id.h>
#include <osmocom/gsupclient/gsup_req.h>
#define OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS 2000
#define LOG_DGSM(imsi, level, fmt, args...) \
LOGP(DDGSM, level, "(IMSI-%s) " fmt, imsi, ##args)

View File

@@ -69,8 +69,6 @@ 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,
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);
enum osmo_gsup_cn_domain cn_domain, void *talloc_ctx);
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);

View File

@@ -23,6 +23,7 @@
#pragma once
#include <stdbool.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/ipa.h>
#include <osmocom/core/tdef.h>
@@ -48,7 +49,6 @@ struct hlr {
/* Control Interface */
struct ctrl_handle *ctrl;
const char *ctrl_bind_addr;
/* Local bind addr */
char *gsup_bind_addr;
@@ -56,6 +56,16 @@ struct hlr {
struct llist_head euse_list;
struct hlr_euse *euse_default;
enum gsm48_gmm_cause reject_cause;
enum gsm48_gmm_cause 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;
/* NCSS (call independent) session guard timeout value */
int ncss_guard_timeout;

View File

@@ -35,15 +35,19 @@ 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
int hlr_vty_is_config_node(struct vty *vty, int node);
int hlr_vty_go_parent(struct vty *vty);
void hlr_vty_init(void);
void hlr_vty_init(void *hlr_ctx);
void dgsm_vty_init(void);

View File

@@ -71,7 +71,7 @@ struct osmo_mdns_rfc_header {
uint16_t nscount; /* Number of authority records */
uint16_t arcount; /* Number of additional records */
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint16_t id;
uint8_t qr:1, opcode:4, aa:1, tc:1, rd:1;
uint8_t ra:1, z:3, rcode:4;
@@ -99,15 +99,12 @@ struct osmo_mdns_rfc_record {
uint8_t *rdata;
};
char *osmo_mdns_rfc_qname_encode(void *ctx, const char *domain);
char *osmo_mdns_rfc_qname_decode(void *ctx, const char *qname, size_t qname_len);
void osmo_mdns_rfc_header_encode(struct msgb *msg, const struct osmo_mdns_rfc_header *hdr);
int osmo_mdns_rfc_header_decode(const uint8_t *data, size_t data_len, struct osmo_mdns_rfc_header *hdr);
int osmo_mdns_rfc_question_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_question *qst);
int osmo_mdns_rfc_question_encode(struct msgb *msg, const struct osmo_mdns_rfc_question *qst);
struct osmo_mdns_rfc_question *osmo_mdns_rfc_question_decode(void *ctx, const uint8_t *data, size_t data_len);
int osmo_mdns_rfc_record_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_record *rec);
int osmo_mdns_rfc_record_encode(struct msgb *msg, const struct osmo_mdns_rfc_record *rec);
struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_t *data, size_t data_len,
size_t *record_len);

View File

@@ -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(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)
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)
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 = 6;
PRAGMA user_version = 7;

View File

@@ -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 *stmt_bootstrap_sql[] = {" >> "$@"
echo "static const char * const stmt_bootstrap_sql[] = {" >> "$@"
cat "$(BOOTSTRAP_SQL)" \
| sed -f "$(srcdir)/db_sql2c.sed" \
>> "$@"

View File

@@ -1,4 +1,4 @@
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
/* (C) 2015-2023 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_data *aud2g,
struct osmo_sub_auth_data *aud3g,
struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data2 *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", hexb(aud3g->u.umts.k));
DBGP("3G: k = %s\n", hex(aud3g->u.umts.k, aud3g->u.umts.k_len));
DBGP("3G: %s = %s\n",
aud3g->u.umts.opc_is_op? "OP" : "opc",
hexb(aud3g->u.umts.opc));
hex(aud3g->u.umts.opc, aud3g->u.umts.opc_len));
DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n",
aud3g->u.umts.ind, aud3g->u.umts.sqn);
}
@@ -115,6 +115,9 @@ 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) {
@@ -123,10 +126,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_auts(vec+i, aud3g, auts,
rc = osmo_auth_gen_vec_auts2(vec+i, aud3g, auts,
rand_auts, rand);
} else {
rc = osmo_auth_gen_vec(vec+i, aud3g, rand);
rc = osmo_auth_gen_vec2(vec+i, aud3g, rand);
}
if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
@@ -154,7 +157,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_vec(&vtmp, aud2g, rand);
rc = osmo_auth_gen_vec2(&vtmp, aud2g, rand);
if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector"
"generation: [%u]: rc = %d\n", i, rc);
@@ -165,7 +168,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_vec(vec+i, aud2g, rand);
rc = osmo_auth_gen_vec2(vec+i, aud2g, rand);
if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
"generation: [%u]: rc = %d\n", i, rc);

View File

@@ -1,6 +1,6 @@
/* OsmoHLR Control Interface implementation */
/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
/* (C) 2017-2023 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, int *maxlen, int *minlen_opc, int *maxlen_opc);
#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_data *aud)
static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *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_data *aud)
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *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),
hexdump_buf(aud->u.umts.k));
osmo_hexdump_nospc(aud->u.umts.k, aud->u.umts.k_len));
/* 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",
hexdump_buf(aud->u.umts.opc),
osmo_hexdump_nospc(aud->u.umts.opc, aud->u.umts.opc_len),
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_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 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_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 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_data aud2g;
struct osmo_sub_auth_data aud3g_unused;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 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)) {
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
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_data aud2g_unused;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g_unused;
struct osmo_sub_auth_data2 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, sizeof(aud3g.u.umts.k)),
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, aud3g.u.umts.k_len),
aud3g.u.umts.opc_is_op ? "OP" : "OPC",
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)),
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, aud3g.u.umts.opc_len),
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;
int maxlen = 0;
int minlen = 0, minlen_opc = 0;
int maxlen = 0, maxlen_opc = 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)) {
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
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, MILENAGE_KEY_LEN * 2, MILENAGE_KEY_LEN * 2, true)) {
if (!osmo_is_hexstr(aud3g.u.umts.opc, minlen_opc * 2, maxlen_opc * 2, true)) {
cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
return CTRL_CMD_ERROR;
}
@@ -749,7 +749,7 @@ static int hlr_ctrl_node_lookup(void *data, vector vline, int *node_type,
return 1;
}
static int hlr_ctrl_cmds_install()
static int hlr_ctrl_cmds_install(void)
{
int rc = 0;
@@ -771,11 +771,8 @@ static int hlr_ctrl_cmds_install()
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr)
{
int rc;
struct ctrl_handle *hdl = ctrl_interface_setup_dynip2(hlr,
hlr->ctrl_bind_addr,
OSMO_CTRL_PORT_HLR,
hlr_ctrl_node_lookup,
_LAST_CTRL_NODE_HLR);
struct ctrl_handle *hdl = ctrl_interface_setup2(hlr, OSMO_CTRL_PORT_HLR, hlr_ctrl_node_lookup,
_LAST_CTRL_NODE_HLR);
if (!hdl)
return NULL;

View File

@@ -1,4 +1,4 @@
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
/* (C) 2015-2023 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 6
#define CURRENT_SCHEMA_VERSION 7
#define SEL_COLUMNS \
"id," \
@@ -235,7 +235,7 @@ void db_close(struct db_context *dbc)
talloc_free(dbc);
}
static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count)
static int db_run_statements(struct db_context *dbc, const char * const *statements, size_t statements_count)
{
int rc = 0;
int i;
@@ -308,7 +308,7 @@ static int
db_upgrade_v1(struct db_context *dbc)
{
int rc;
const char *statements[] = {
const char * const statements[] = {
"ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL",
"PRAGMA user_version = 1",
};
@@ -324,7 +324,7 @@ db_upgrade_v1(struct db_context *dbc)
static int db_upgrade_v2(struct db_context *dbc)
{
int rc;
const char *statements[] = {
const char * const statements[] = {
"ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14)",
"PRAGMA user_version = 2",
};
@@ -437,7 +437,7 @@ static int db_upgrade_v3(struct db_context *dbc)
"ms_purged_ps," \
"last_lu_seen"
const char *statements[] = {
const char * const statements[] = {
"BEGIN TRANSACTION",
"CREATE TEMPORARY TABLE subscriber_backup" SUBSCR_V3_CREATE,
"INSERT INTO subscriber_backup SELECT " SUBSCR_V2_COLUMN_NAMES " FROM subscriber",
@@ -460,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 *statements[] = {
const char * const statements[] = {
"ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL",
"PRAGMA user_version = 4",
};
@@ -476,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 *statements[] = {
const char * const statements[] = {
"ALTER TABLE subscriber ADD COLUMN vlr_via_proxy VARCHAR",
"ALTER TABLE subscriber ADD COLUMN sgsn_via_proxy VARCHAR",
"PRAGMA user_version = 5",
@@ -493,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 *statements[] = {
const char * const statements[] = {
"CREATE TABLE ind (\n"
" -- 3G auth IND pool to be used for this VLR\n"
" ind INTEGER PRIMARY KEY,\n"
@@ -513,6 +513,46 @@ 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,
@@ -521,6 +561,7 @@ 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)

View File

@@ -1,4 +1,4 @@
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
/* (C) 2015-2023 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 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)
* 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)
{
const uint8_t *text;
size_t col_len;
@@ -84,9 +84,15 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
/* 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) {
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected length %lu but has length %lu\n", col_name,
dst_len, col_len);
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);
return -EIO;
}
@@ -95,8 +101,11 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
LOGAUC(imsi, LOGL_ERROR, "Error reading %s\n", col_name);
return -EIO;
}
osmo_hexparse((void *)text, dst, dst_len);
return 0;
if (osmo_hexparse((void *)text, dst, dst_len_max) != col_len)
return -EINVAL;
return col_len;
}
/* obtain the authentication data for a given imsi
@@ -104,8 +113,8 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
* -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_data *aud2g,
struct osmo_sub_auth_data *aud3g,
struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data2 *aud3g,
int64_t *subscr_id)
{
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI];
@@ -139,7 +148,8 @@ 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), stmt, 2, "Ki", imsi))
if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), sizeof(aud2g->u.gsm.ki),
stmt, 2, "Ki", imsi) < 0)
goto end_2g;
aud2g->algo = sqlite3_column_int(stmt, 1);
aud2g->type = OSMO_AUTH_TYPE_GSM;
@@ -148,24 +158,30 @@ 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 */
if (hexparse_stmt(aud3g->u.umts.k, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi)) {
rc = hexparse_stmt(aud3g->u.umts.k, 16, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi);
if (rc < 0) {
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)) {
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi)) {
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi);
if (rc < 0) {
ret = -EIO;
goto out;
}
aud3g->u.umts.opc_len = rc;
aud3g->u.umts.opc_is_op = 1;
} else {
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi)) {
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi);
if (rc < 0) {
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);
@@ -191,7 +207,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_data aud2g, aud3g;
struct osmo_sub_auth_data2 aud2g, aud3g;
int64_t subscr_id;
int ret = 0;
int rc;

View File

@@ -1,4 +1,4 @@
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -238,8 +238,9 @@ 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:
case OSMO_AUTH_ALG_XOR_2G:
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",
@@ -267,11 +268,12 @@ 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:
case OSMO_AUTH_ALG_XOR_3G:
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));
@@ -284,12 +286,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, 32, true)) {
if (!osmo_is_hexstr(aud->u.umts.k, 32, 64, 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, 32, true)) {
if (!osmo_is_hexstr(aud->u.umts.opc, 32, 64, true)) {
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" Invalid OP/OPC: '%s'\n", aud->u.umts.opc);
return -EINVAL;

View File

@@ -170,7 +170,7 @@ void dgsm_init(void *ctx)
g_hlr->mslookup.server.local_attach_max_age = 60 * 60;
g_hlr->mslookup.client.result_timeout_milliseconds = 2000;
g_hlr->mslookup.client.result_timeout_milliseconds = OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS;
g_hlr->gsup_unit_name.unit_name = "HLR";
g_hlr->gsup_unit_name.serno = "unnamed-HLR";
@@ -191,7 +191,7 @@ void dgsm_start(void *ctx)
dgsm_mdns_client_config_apply();
}
void dgsm_stop()
void dgsm_stop(void)
{
g_hlr->mslookup.allow_startup = false;
mslookup_server_mdns_config_apply();

View File

@@ -447,8 +447,8 @@ int config_write_mslookup(struct vty *vty)
llist_for_each_entry(msc, &g_hlr->mslookup.server.local_site_services, entry) {
if (!osmo_ipa_name_cmp(&mslookup_server_msc_wildcard, &msc->name))
continue;
vty_out(vty, " msc %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
config_write_msc_services(vty, " ", msc);
vty_out(vty, " msc ipa-name %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
config_write_msc_services(vty, " ", msc);
}
/* If the server is disabled, still output the above to not lose the service config. */
@@ -475,6 +475,10 @@ int config_write_mslookup(struct vty *vty)
vty_out(vty, " mdns domain-suffix %s%s",
g_hlr->mslookup.client.mdns.domain_suffix,
VTY_NEWLINE);
if (g_hlr->mslookup.client.result_timeout_milliseconds != OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS)
vty_out(vty, " timeout %u%s",
g_hlr->mslookup.client.result_timeout_milliseconds,
VTY_NEWLINE);
}
return CMD_SUCCESS;

View File

@@ -32,6 +32,7 @@
#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, \
@@ -179,11 +180,9 @@ 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);
if (rc < 0) {
/* conn is already invalid here! */
return -1;
}
msgb_free(msg);
if (rc < 0) /* conn is already invalid here! */
return -1;
return 0;
}
@@ -446,19 +445,16 @@ 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,
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)
enum osmo_gsup_cn_domain cn_domain,
void *talloc_ctx)
{
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){
@@ -467,27 +463,29 @@ int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup,
osmo_strlcpy(gsup->imsi, imsi, sizeof(gsup->imsi));
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);
len = gsm48_encode_bcd_number(msisdn_buf, OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN, 0, msisdn);
if (len < 1) {
LOGP(DLGSUP, LOGL_ERROR, "%s: Error: cannot encode MSISDN '%s'\n", imsi, msisdn);
return -ENOSPC;
}
gsup->msisdn_enc = msisdn_enc;
gsup->msisdn_enc = msisdn_buf;
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) {
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);
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);
}
}
return 0;

View File

@@ -85,8 +85,6 @@ 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;
@@ -131,8 +129,7 @@ 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, msisdn_enc,
sizeof(msisdn_enc), apn, sizeof(apn), cn_domain) != 0) {
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, cn_domain, OTC_SELECT) != 0) {
LOGP(DLGSUP, LOGL_ERROR,
"IMSI='%s': Cannot notify GSUP client; could not create gsup message "
"for %s:%u\n", subscr->imsi,
@@ -324,7 +321,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, GMM_CAUSE_IMSI_UNKNOWN, "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");
@@ -568,12 +565,12 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
return 0;
}
static void print_usage()
static void print_usage(void)
{
printf("Usage: osmo-hlr\n");
}
static void print_help()
static void print_help(void)
{
printf(" -h --help This text.\n");
printf(" -c --config-file filename The config file to use.\n");
@@ -727,7 +724,7 @@ static void signal_hdlr(int signal)
}
static const char vlr_copyright[] =
"Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
"Copyright (C) 2016-2023 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";
@@ -759,6 +756,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 = 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;
@@ -775,7 +774,7 @@ int main(int argc, char **argv)
osmo_stats_init(hlr_ctx);
vty_init(&vty_info);
ctrl_vty_init(hlr_ctx);
hlr_vty_init();
hlr_vty_init(hlr_ctx);
dgsm_vty_init();
osmo_cpu_sched_vty_init(hlr_ctx);
handle_options(argc, argv);
@@ -816,8 +815,7 @@ int main(int argc, char **argv)
}
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(hlr_ctx, NULL, vty_get_bind_addr(),
OSMO_VTY_PORT_HLR);
rc = telnet_init_default(hlr_ctx, NULL, OSMO_VTY_PORT_HLR);
if (rc < 0)
return rc;
@@ -830,7 +828,6 @@ int main(int argc, char **argv)
}
proxy_init(g_hlr->gs);
g_hlr->ctrl_bind_addr = ctrl_vty_get_bind_addr();
g_hlr->ctrl = hlr_controlif_setup(g_hlr);
dgsm_start(hlr_ctx);

View File

@@ -51,7 +51,7 @@ static struct {
.db_upgrade = false,
};
static void print_help()
static void print_help(void)
{
printf("\n");
printf("Usage: osmo-hlr-db-tool [-l <hlr.db>] [create|import-nitb-db <nitb.db>]\n");

View File

@@ -122,9 +122,40 @@ void ussd_route_del(struct hlr_ussd_route *rt)
talloc_free(rt);
}
static struct hlr_ussd_route *ussd_route_lookup_7bit(struct hlr *hlr, const char *ussd_code)
static struct hlr_ussd_route *ussd_route_lookup_for_req(struct hlr *hlr, const struct ss_request *req)
{
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 "
@@ -603,7 +634,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_7bit(hlr, (const char *) req.ussd_text);
rt = ussd_route_lookup_for_req(hlr, &req);
if (rt) {
if (rt->is_external) {
ss->is_external = true;
@@ -631,7 +662,8 @@ 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_INV_MAND_INFO, "CONTINUE for unknown SS session");
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_MSGT_INCOMP_P_STATE,
"CONTINUE for unknown SS session");
return;
}
@@ -652,6 +684,8 @@ 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;
}
@@ -682,4 +716,5 @@ 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);
}

View File

@@ -25,7 +25,13 @@
*
*/
#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>
@@ -40,6 +46,36 @@
#include <osmocom/hlr/hlr_ussd.h>
#include <osmocom/hlr/gsup_server.h>
static const struct value_string gsm48_gmm_cause_vty_names[] = {
{ GMM_CAUSE_IMSI_UNKNOWN, "imsi-unknown" },
{ GMM_CAUSE_ILLEGAL_MS, "illegal-ms" },
{ GMM_CAUSE_PLMN_NOTALLOWED, "plmn-not-allowed" },
{ GMM_CAUSE_LA_NOTALLOWED, "la-not-allowed" },
{ GMM_CAUSE_ROAMING_NOTALLOWED, "roaming-not-allowed" },
{ GMM_CAUSE_NO_SUIT_CELL_IN_LA, "no-suitable-cell-in-la" },
{ GMM_CAUSE_NET_FAIL, "net-fail" },
{ GMM_CAUSE_CONGESTION, "congestion" },
{ GMM_CAUSE_GSM_AUTH_UNACCEPT, "auth-unacceptable" },
{ GMM_CAUSE_PROTO_ERR_UNSPEC, "proto-error-unspec" },
{ 0, NULL },
};
/* TS 24.008 4.4.4.7 */
static const struct value_string gsm48_gmm_cause_vty_descs[] = {
{ GMM_CAUSE_IMSI_UNKNOWN, " #02: (IMSI unknown in HLR)" },
{ GMM_CAUSE_ILLEGAL_MS, " #03 (Illegal MS)" },
{ GMM_CAUSE_PLMN_NOTALLOWED, " #11: (PLMN not allowed)" },
{ GMM_CAUSE_LA_NOTALLOWED, " #12: (Location Area not allowed)" },
{ GMM_CAUSE_ROAMING_NOTALLOWED, " #13: (Roaming not allowed in this location area)" },
{ GMM_CAUSE_NO_SUIT_CELL_IN_LA, " #15: (No Suitable Cells In Location Area [continue search in PLMN])." },
{ GMM_CAUSE_NET_FAIL, " #17: (Network Failure)" },
{ GMM_CAUSE_CONGESTION, " #22: (Congestion)" },
{ GMM_CAUSE_GSM_AUTH_UNACCEPT, " #23: (GSM authentication unacceptable [UMTS])" },
{ GMM_CAUSE_PROTO_ERR_UNSPEC, "#111: (Protocol error, unspecified)" },
{ 0, NULL },
};
struct cmd_node hlr_node = {
HLR_NODE,
"%s(config-hlr)# ",
@@ -70,9 +106,194 @@ 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 != 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), 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->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))
@@ -107,6 +328,37 @@ 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;
@@ -158,7 +410,7 @@ DEFUN(cfg_hlr_gsup_ipa_name,
{
if (vty->type != VTY_FILE) {
vty_out(vty, "gsup/ipa-name: The GSUP IPA name cannot be changed at run-time; "
"It can only be set in the configuraton file.%s", VTY_NEWLINE);
"It can only be set in the configuration file.%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -358,6 +610,21 @@ DEFUN(cfg_ncss_guard_timeout, cfg_ncss_guard_timeout_cmd,
return CMD_SUCCESS;
}
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[1]);
OSMO_ASSERT(cause_code >= 0);
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"
@@ -450,8 +717,22 @@ int hlr_vty_is_config_node(struct vty *vty, int node)
}
}
void hlr_vty_init(void)
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) (", "|", ")",
VTY_DO_LOWER);
cfg_reject_cause_cmd.doc =
vty_cmd_string_from_valstr(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",
"\n", "", 0);
logging_vty_add_cmds();
osmo_talloc_vty_add_cmds();
osmo_stats_vty_add_cmds();
@@ -467,6 +748,20 @@ void hlr_vty_init(void)
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);
@@ -478,6 +773,7 @@ void hlr_vty_init(void)
install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd);
install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd);
install_element(HLR_NODE, &cfg_ncss_guard_timeout_cmd);
install_element(HLR_NODE, &cfg_reject_cause_cmd);
install_element(HLR_NODE, &cfg_store_imei_cmd);
install_element(HLR_NODE, &cfg_no_store_imei_cmd);
install_element(HLR_NODE, &cfg_subscr_create_on_demand_cmd);

View File

@@ -1,5 +1,5 @@
/* OsmoHLR subscriber management VTY implementation */
/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
/* (C) 2017-2023 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_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 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_data){};
aud2g = (struct osmo_sub_auth_data2){};
}
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_data){};
aud3g = (struct osmo_sub_auth_data2){};
}
if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
@@ -154,9 +154,10 @@ 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", hexdump_buf(aud3g.u.umts.k), 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, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
osmo_hexdump_nospc(aud3g.u.umts.opc, aud3g.u.umts.opc_len), 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);
@@ -460,20 +461,27 @@ static bool is_hexkey_valid(struct vty *vty, const char *label,
return false;
}
#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor)"
#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor-2g)"
#define AUTH_ALG_TYPES_2G_HELP \
"Use COMP128v1 algorithm\n" \
"Use COMP128v2 algorithm\n" \
"Use COMP128v3 algorithm\n" \
"Use XOR algorithm\n"
"Use XOR-2G algorithm\n"
#define AUTH_ALG_TYPES_3G "milenage"
#define AUTH_ALG_TYPES_3G "(milenage|tuak)"
#define AUTH_ALG_TYPES_3G_HELP \
"Use Milenage algorithm\n"
"Use Milenage algorithm\n" \
"Use TUAK algorithm\n"
bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
int *minlen, int *maxlen)
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc)
{
/* 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;
@@ -486,13 +494,28 @@ 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")) {
*algo = OSMO_AUTH_ALG_XOR;
} else if (!strcasecmp(alg_str, "xor-3g")) {
*algo = OSMO_AUTH_ALG_XOR_3G;
*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;
@@ -548,7 +571,7 @@ DEFUN(subscriber_aud2g,
.u.gsm.ki = ki,
};
if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -607,21 +630,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 hexadecimal characters\n"
"Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
"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 IND bit length\n" "IND bit length value (default: 5)\n")
{
struct hlr_subscriber subscr;
int minlen = 0;
int maxlen = 0;
int minlen = 0, minlen_opc = 0;
int maxlen = 0, maxlen_opc = 0;
int rc;
const char *id_type = argv[0];
const char *id = argv[1];
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;
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;
struct sub_auth_data_str aud3g = {
.type = OSMO_AUTH_TYPE_UMTS,
.u.umts = {
@@ -632,7 +655,7 @@ DEFUN(subscriber_aud3g,
},
};
if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -640,8 +663,7 @@ 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,
MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc, minlen_opc, maxlen_opc))
return CMD_WARNING;
if (get_subscr_by_argv(vty, id_type, id, &subscr))
@@ -659,11 +681,11 @@ DEFUN(subscriber_aud3g,
DEFUN(subscriber_aud3g_xor,
subscriber_aud3g_xor_cmd,
SUBSCR_UPDATE "aud3g xor k K"
SUBSCR_UPDATE "aud3g xor-3g k K"
" [ind-bitlen] [<0-28>]",
SUBSCR_UPDATE_HELP
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
"Use XOR algorithm\n"
"Use XOR-3G 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")
{
@@ -685,8 +707,8 @@ DEFUN(subscriber_aud3g_xor,
},
};
if (!auth_algo_parse("xor", &aud3g.algo, &minlen, &maxlen)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor", VTY_NEWLINE);
if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen, NULL, NULL)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor-3g", VTY_NEWLINE);
return CMD_WARNING;
}

View File

@@ -136,7 +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, GMM_CAUSE_IMSI_UNKNOWN, "Subscriber does not exist");
lu_failure(lu, g_hlr->reject_cause, "Subscriber does not exist");
return;
}
@@ -241,13 +241,11 @@ 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, msisdn_enc, sizeof(msisdn_enc),
apn, sizeof(apn),
lu->is_ps? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS)) {
subscr->msisdn,
lu->is_ps ? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS,
OTC_SELECT)) {
lu_failure(lu, GMM_CAUSE_NET_FAIL, "cannot encode Insert Subscriber Data message");
return;
}
@@ -277,6 +275,7 @@ 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:
@@ -314,7 +313,7 @@ static struct osmo_fsm lu_fsm = {
.cleanup = lu_fsm_cleanup,
};
static __attribute__((constructor)) void lu_fsm_init()
static __attribute__((constructor)) void lu_fsm_init(void)
{
OSMO_ASSERT(osmo_fsm_register(&lu_fsm) == 0);
}

View File

@@ -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=0:0:0
LIBVERSION=1:1:0
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include
AM_CFLAGS = -fPIC -Wall $(PCSC_CFLAGS) $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS)

View File

@@ -40,7 +40,7 @@ int osmo_mdns_msg_request_encode(void *ctx, struct msgb *msg, const struct osmo_
qst.domain = req->domain;
qst.qtype = req->type;
qst.qclass = OSMO_MDNS_RFC_CLASS_IN;
if (osmo_mdns_rfc_question_encode(ctx, msg, &qst) != 0)
if (osmo_mdns_rfc_question_encode(msg, &qst) != 0)
return -EINVAL;
return 0;
@@ -106,7 +106,7 @@ int osmo_mdns_msg_answer_encode(void *ctx, struct msgb *msg, const struct osmo_m
rec.rdlength = ans_record->length;
rec.rdata = ans_record->data;
if (osmo_mdns_rfc_record_encode(ctx, msg, &rec) != 0)
if (osmo_mdns_rfc_record_encode(msg, &rec) != 0)
return -EINVAL;
}

View File

@@ -27,91 +27,9 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/bitvec.h>
#include <osmocom/core/logging.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/mslookup/mdns_rfc.h>
/*
* Encode/decode IEs
*/
/*! Encode a domain string as qname (RFC 1035 4.1.2).
* \param[in] domain multiple labels separated by dots, e.g. "sip.voice.1234.msisdn".
* \returns allocated buffer with length-value pairs for each label (e.g. 0x03 "sip" 0x05 "voice" ...), NULL on error.
*/
char *osmo_mdns_rfc_qname_encode(void *ctx, const char *domain)
{
char *domain_dup;
char *domain_iter;
char buf[OSMO_MDNS_RFC_MAX_NAME_LEN + 2] = ""; /* len(qname) is len(domain) +1 */
struct osmo_strbuf sb = { .buf = buf, .len = sizeof(buf) };
char *label;
if (strlen(domain) > OSMO_MDNS_RFC_MAX_NAME_LEN)
return NULL;
domain_iter = domain_dup = talloc_strdup(ctx, domain);
while ((label = strsep(&domain_iter, "."))) {
size_t len = strlen(label);
/* Empty domain, dot at start, two dots in a row, or ending with a dot */
if (!len)
goto error;
OSMO_STRBUF_PRINTF(sb, "%c%s", (char)len, label);
}
talloc_free(domain_dup);
return talloc_strdup(ctx, buf);
error:
talloc_free(domain_dup);
return NULL;
}
/*! Decode a domain string from a qname (RFC 1035 4.1.2).
* \param[in] qname buffer with length-value pairs for each label (e.g. 0x03 "sip" 0x05 "voice" ...)
* \param[in] qname_max_len amount of bytes that can be read at most from the memory location that qname points to.
* \returns allocated buffer with domain string, multiple labels separated by dots (e.g. "sip.voice.1234.msisdn"),
* NULL on error.
*/
char *osmo_mdns_rfc_qname_decode(void *ctx, const char *qname, size_t qname_max_len)
{
const char *next_label, *qname_end = qname + qname_max_len;
char buf[OSMO_MDNS_RFC_MAX_NAME_LEN + 1];
int i = 0;
if (qname_max_len < 1)
return NULL;
while (*qname) {
size_t len;
if (i >= qname_max_len)
return NULL;
len = *qname;
next_label = qname + len + 1;
if (next_label >= qname_end || i + len > OSMO_MDNS_RFC_MAX_NAME_LEN)
return NULL;
if (i) {
/* Two dots in a row is not allowed */
if (buf[i - 1] == '.')
return NULL;
buf[i] = '.';
i++;
}
memcpy(buf + i, qname + 1, len);
i += len;
qname = next_label;
}
buf[i] = '\0';
return talloc_strdup(ctx, buf);
}
/*
* Encode/decode message sections
*/
@@ -151,20 +69,17 @@ int osmo_mdns_rfc_header_decode(const uint8_t *data, size_t data_len, struct osm
/*! Encode question section (RFC 1035 4.1.2).
* \param[in] msgb mesage buffer to which the encoded data will be appended.
*/
int osmo_mdns_rfc_question_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_question *qst)
int osmo_mdns_rfc_question_encode(struct msgb *msg, const struct osmo_mdns_rfc_question *qst)
{
char *qname;
size_t qname_len;
uint8_t *qname_buf;
uint8_t *buf;
size_t buf_len;
/* qname */
qname = osmo_mdns_rfc_qname_encode(ctx, qst->domain);
if (!qname)
buf_len = strlen(qst->domain) + 1;
buf = msgb_put(msg, buf_len);
if (osmo_apn_from_str(buf, buf_len, qst->domain) < 0)
return -EINVAL;
qname_len = strlen(qname) + 1;
qname_buf = msgb_put(msg, qname_len);
memcpy(qname_buf, qname, qname_len);
talloc_free(qname);
msgb_put_u8(msg, 0x00);
/* qtype and qclass */
msgb_put_u16(msg, qst->qtype);
@@ -182,21 +97,25 @@ struct osmo_mdns_rfc_question *osmo_mdns_rfc_question_decode(void *ctx, const ui
if (data_len < 6)
return NULL;
/* qname */
ret = talloc_zero(ctx, struct osmo_mdns_rfc_question);
if (!ret)
return NULL;
ret->domain = osmo_mdns_rfc_qname_decode(ret, (const char *)data, qname_len);
if (!ret->domain) {
talloc_free(ret);
return NULL;
}
/* qname */
ret->domain = talloc_size(ret, qname_len - 1);
if (!ret->domain)
goto error;
if (!osmo_apn_to_str(ret->domain, data, qname_len - 1))
goto error;
/* qtype and qclass */
ret->qtype = osmo_load16be(data + qname_len);
ret->qclass = osmo_load16be(data + qname_len + 2);
return ret;
error:
talloc_free(ret);
return NULL;
}
/*
@@ -206,20 +125,17 @@ struct osmo_mdns_rfc_question *osmo_mdns_rfc_question_decode(void *ctx, const ui
/*! Encode one resource record (RFC 1035 4.1.3).
* \param[in] msgb mesage buffer to which the encoded data will be appended.
*/
int osmo_mdns_rfc_record_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_record *rec)
int osmo_mdns_rfc_record_encode(struct msgb *msg, const struct osmo_mdns_rfc_record *rec)
{
char *name;
size_t name_len;
uint8_t *buf;
size_t buf_len;
/* name */
name = osmo_mdns_rfc_qname_encode(ctx, rec->domain);
if (!name)
buf_len = strlen(rec->domain) + 1;
buf = msgb_put(msg, buf_len);
if (osmo_apn_from_str(buf, buf_len, rec->domain) < 0)
return -EINVAL;
name_len = strlen(name) + 1;
buf = msgb_put(msg, name_len);
memcpy(buf, name, name_len);
talloc_free(name);
msgb_put_u8(msg, 0x00);
/* type, class, ttl, rdlength */
msgb_put_u16(msg, rec->type);
@@ -237,15 +153,26 @@ int osmo_mdns_rfc_record_encode(void *ctx, struct msgb *msg, const struct osmo_m
struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_t *data, size_t data_len,
size_t *record_len)
{
struct osmo_mdns_rfc_record *ret = talloc_zero(ctx, struct osmo_mdns_rfc_record);
struct osmo_mdns_rfc_record *ret;
size_t name_len;
/* name */
ret->domain = osmo_mdns_rfc_qname_decode(ret, (const char *)data, data_len - 10);
/* name length: represented as a series of labels, and terminated by a
* label with zero length (RFC 1035 3.3). A label with zero length is a
* NUL byte. */
name_len = strnlen((const char *)data, data_len - 10) + 1;
if (data[name_len])
return NULL;
/* allocate ret + ret->domain */
ret = talloc_zero(ctx, struct osmo_mdns_rfc_record);
if (!ret)
return NULL;
ret->domain = talloc_size(ctx, name_len - 1);
if (!ret->domain)
goto error;
name_len = strlen(ret->domain) + 2;
if (name_len + 10 > data_len)
/* name */
if (!osmo_apn_to_str(ret->domain, data, name_len - 1))
goto error;
/* type, class, ttl, rdlength */
@@ -259,7 +186,7 @@ struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_
/* rdata */
ret->rdata = talloc_memdup(ret, data + name_len + 10, ret->rdlength);
if (!ret->rdata)
return NULL;
goto error;
*record_len = name_len + 10 + ret->rdlength;
return ret;

View File

@@ -53,7 +53,7 @@ static void print_version(void)
"\n");
}
static void print_help()
static void print_help(void)
{
print_version();
printf(
@@ -419,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);
@@ -555,15 +555,15 @@ int socket_init(const char *sock_path)
return 0;
}
void socket_close()
void socket_close(void)
{
struct socket_client *c, *n;
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);
}
}

View File

@@ -49,7 +49,7 @@ static void set_result(struct osmo_mslookup_result *result,
result->age = age;
}
const struct mslookup_service_host *mslookup_server_get_local_gsup_addr()
const struct mslookup_service_host *mslookup_server_get_local_gsup_addr(void)
{
static struct mslookup_service_host gsup_bind = {};
struct mslookup_service_host *host;

View File

@@ -121,7 +121,7 @@ void osmo_mslookup_server_mdns_stop(struct osmo_mslookup_server_mdns *server)
talloc_free(server);
}
void mslookup_server_mdns_config_apply()
void mslookup_server_mdns_config_apply(void)
{
/* Check whether to start/stop/restart mDNS server */
bool should_run;

View File

@@ -29,6 +29,7 @@
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/gsupclient/gsup_req.h>
#include <osmocom/hlr/hlr.h>
#include <osmocom/hlr/logging.h>
#include <osmocom/hlr/proxy.h>
#include <osmocom/hlr/remote_hlr.h>
@@ -80,7 +81,19 @@ static void proxy_deferred_gsup_req_add(struct proxy *proxy, struct osmo_gsup_re
static void proxy_pending_req_remote_hlr_connect_result(struct osmo_gsup_req *req, struct remote_hlr *remote_hlr)
{
if (!remote_hlr || !remote_hlr_is_up(remote_hlr)) {
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "Proxy: Failed to connect to home HLR");
/* Do not respond with an error to a CHECK_IMEI_REQUEST as osmo-msc will send a LU Reject Cause #6
* Just respond ACK and deal with the IMSI check that comes next. */
if (req->gsup.message_type == OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST) {
/* Accept all IMEIs */
struct osmo_gsup_message gsup_reply = (struct osmo_gsup_message){
.message_type = OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,
.imei_result = OSMO_GSUP_IMEI_RESULT_ACK,
};
osmo_gsup_req_respond(req, &gsup_reply, false, true);
return;
}
osmo_gsup_req_respond_err(req, g_hlr->no_proxy_reject_cause,
"Proxy: Failed to connect to home HLR");
return;
}
@@ -190,6 +203,7 @@ int proxy_subscr_create_or_update(struct proxy *proxy, const struct proxy_subscr
int _proxy_subscr_del(struct proxy_subscr_listentry *e)
{
llist_del(&e->entry);
talloc_free(e);
return 0;
}

View File

@@ -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_srcdir)/src/auc.c \
$(top_srcdir)/src/logging.c \
$(top_builddir)/src/auc.o \
$(top_builddir)/src/logging.o \
$(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_srcdir)/src/auc.c \
$(top_srcdir)/src/logging.c \
$(top_builddir)/src/auc.o \
$(top_builddir)/src/logging.o \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(NULL)

View File

@@ -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_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec;
int rc;
comment_start();
aud2g = (struct osmo_sub_auth_data){
aud2g = (struct osmo_sub_auth_data2){
.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_data){ 0 };
aud3g = (struct osmo_sub_auth_data2){ 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_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec;
int rc;
comment_start();
aud2g = (struct osmo_sub_auth_data){
aud2g = (struct osmo_sub_auth_data2){
.type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1,
};
@@ -194,9 +194,11 @@ 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_data){
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,
.u.umts.sqn = 31,
};
@@ -292,8 +294,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_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec;
struct osmo_auth_vector vecs[3];
uint8_t auts[14];
@@ -302,11 +304,13 @@ static void test_gen_vectors_3g_only(void)
comment_start();
aud2g = (struct osmo_sub_auth_data){ 0 };
aud2g = (struct osmo_sub_auth_data2){ 0 };
aud3g = (struct osmo_sub_auth_data){
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,
.u.umts.sqn = 31,
};
@@ -466,18 +470,20 @@ static void test_gen_vectors_3g_only(void)
* 2G and 3G authentication */
static void test_gen_vectors_3g_xor(void)
{
struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec;
int rc;
comment_start();
aud2g = (struct osmo_sub_auth_data){ 0 };
aud2g = (struct osmo_sub_auth_data2){ 0 };
aud3g = (struct osmo_sub_auth_data){
aud3g = (struct osmo_sub_auth_data2){
.type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_XOR,
.algo = OSMO_AUTH_ALG_XOR_3G,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 0,
};
@@ -509,7 +515,7 @@ static void test_gen_vectors_3g_xor(void)
}
/* Test a variety of invalid authentication data combinations */
void test_gen_vectors_bad_args()
void test_gen_vectors_bad_args(void)
{
struct osmo_auth_vector vec;
uint8_t auts[14];
@@ -517,39 +523,43 @@ void test_gen_vectors_bad_args()
int rc;
int i;
struct osmo_sub_auth_data aud2g = {
struct osmo_sub_auth_data2 aud2g = {
.type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1,
};
struct osmo_sub_auth_data aud3g = {
struct osmo_sub_auth_data2 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_data aud2g_noalg = {
struct osmo_sub_auth_data2 aud2g_noalg = {
.type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_NONE,
};
struct osmo_sub_auth_data aud3g_noalg = {
struct osmo_sub_auth_data2 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_data aud_notype = {
struct osmo_sub_auth_data2 aud_notype = {
.type = OSMO_AUTH_TYPE_NONE,
.algo = OSMO_AUTH_ALG_MILENAGE,
};
struct osmo_sub_auth_data no_aud = {
struct osmo_sub_auth_data2 no_aud = {
.type = OSMO_AUTH_TYPE_NONE,
.algo = OSMO_AUTH_ALG_NONE,
};
struct {
struct osmo_sub_auth_data *aud2g;
struct osmo_sub_auth_data *aud3g;
struct osmo_sub_auth_data2 *aud2g;
struct osmo_sub_auth_data2 *aud3g;
uint8_t *rand_auts;
uint8_t *auts;
const char *label;

View File

@@ -24,43 +24,46 @@
static void {func_name}(void)
{{
struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_auth_vector vec;
int rc;
struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec;
int rc;
comment_start();
comment_start();
aud2g = (struct osmo_sub_auth_data){{ 0 }};
aud2g = (struct osmo_sub_auth_data2){{ 0 }};
aud3g = (struct osmo_sub_auth_data){{
.type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE,
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,
.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 = (struct osmo_auth_vector){{ {{0}} }};
vec.res_len = 8;
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();
}}

View File

@@ -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; \
@@ -100,7 +100,7 @@ int rand_get(uint8_t *rand, unsigned int len)
FUNCTIONS
int main()
int main(int argc, char **argv)
{
printf("3GPP TS 55.205 Test Sets\n");
void *tall_ctx = talloc_named_const(NULL, 1, "test");

View File

@@ -1,7 +1,10 @@
AM_CFLAGS = \
AM_CPPFLAGS = \
$(all_includes) \
-I$(top_srcdir)/include \
-I$(top_builddir)/include \
$(NULL)
AM_CFLAGS = \
-Wall \
-ggdb3 \
$(LIBOSMOCORE_CFLAGS) \

View File

@@ -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_data *aud2g,
struct osmo_sub_auth_data *aud3g,
struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data2 *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_data g_aud2g;
static struct osmo_sub_auth_data g_aud3g;
static struct osmo_sub_auth_data2 g_aud2g;
static struct osmo_sub_auth_data2 g_aud3g;
static int g_rc;
static int64_t g_id;
@@ -180,18 +180,21 @@ void dump_subscr(struct hlr_subscriber *subscr)
#undef Pb
}
void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
{
if (aud->type == OSMO_AUTH_TYPE_NONE) {
fprintf(stderr, "%s: none\n", label);
return;
}
fprintf(stderr, "%s: struct osmo_sub_auth_data {\n", label);
fprintf(stderr, "%s: struct osmo_sub_auth_data2 {\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));
@@ -200,9 +203,9 @@ void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
Phex(u.gsm.ki);
break;
case OSMO_AUTH_TYPE_UMTS:
Phex(u.umts.opc);
Phexl(u.umts.opc, u.umts.opc_len);
Pf(u.umts.opc_is_op, "%u");
Phex(u.umts.k);
Phexl(u.umts.k, u.umts.k_len);
Phex(u.umts.amf);
if (aud->u.umts.sqn) {
Pf(u.umts.sqn, "%"PRIu64);
@@ -219,6 +222,7 @@ void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
#undef Pf
#undef Phex
#undef Phexl
}
void db_raw_sql(struct db_context *dbc, const char *sql)
@@ -246,7 +250,7 @@ static int db_subscr_lu_str(struct db_context *dbc, int64_t subscr_id,
return db_subscr_lu(dbc, subscr_id, &vlr_nr, is_ps, NULL);
}
static void test_subscr_create_update_sel_delete()
static void test_subscr_create_update_sel_delete(void)
{
int64_t id0, id1, id2, id_short;
comment_start();
@@ -541,7 +545,7 @@ static const struct sub_auth_data_str *mk_aud_3g(enum osmo_auth_algo algo,
return &aud;
}
static void test_subscr_aud()
static void test_subscr_aud(void)
{
int64_t id;
@@ -586,7 +590,7 @@ static void test_subscr_aud()
ASSERT_SEL_AUD(imsi0, 0, id);
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
0);
ASSERT_SEL_AUD(imsi0, 0, id);
@@ -604,7 +608,7 @@ static void test_subscr_aud()
-ENOENT);
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
0);
ASSERT_SEL_AUD(imsi0, 0, id);
@@ -707,12 +711,12 @@ static void test_subscr_aud()
ASSERT_SEL_AUD(imsi0, 0, id);
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")),
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "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, "f00")),
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")),
-EINVAL);
ASSERT_SEL_AUD(imsi0, 0, id);
@@ -783,7 +787,7 @@ static void test_subscr_aud()
/* Make each key too short in this test. Note that we can't set them longer than the allowed size without changing the
* table structure. */
static void test_subscr_aud_invalid_len()
static void test_subscr_aud_invalid_len(void)
{
int64_t id;
@@ -845,7 +849,7 @@ static void test_subscr_aud_invalid_len()
comment_end();
}
static void test_subscr_sqn()
static void test_subscr_sqn(void)
{
int64_t id;
@@ -918,7 +922,7 @@ static void test_subscr_sqn()
comment_end();
}
static void test_ind()
static void test_ind(void)
{
comment_start();

View File

@@ -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_data {
2G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.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, "CededEffacedAceFacedBadFadedBeef")) --> 0
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = XOR,
.algo = XOR-2G,
.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, "CededEffacedAceFacedBadFadedBeef")) --> 0
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = XOR,
.algo = XOR-2G,
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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, "f000000000000f00000000000f000000f00000000")) --> -EINVAL
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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, "f00")) --> -EINVAL
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
2G: struct osmo_sub_auth_data2 {
.type = GSM,
.algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
}
3G: struct osmo_sub_auth_data {
3G: struct osmo_sub_auth_data2 {
.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 length 16 but has length 15
DAUC IMSI='123456789000000': Error reading Ki, expected min 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 length 16 but has length 15
DAUC IMSI='123456789000000': Error reading K, expected min 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 length 16 but has length 15
DAUC IMSI='123456789000000': Error reading OP, expected min 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 length 16 but has length 15
DAUC IMSI='123456789000000': Error reading OPC, expected min 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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.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_data {
3G: struct osmo_sub_auth_data2 {
.type = UMTS,
.algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',

View File

@@ -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 ki 55555555555555555555555555555555
OsmoHLR# subscriber imsi 5555555 update aud2g xor-2g ki 55555555555555555555555555555555
OsmoHLR# subscriber imsi 5555555 update aud3g milenage k 55555555555555555555555555555555 opc 55555555555555555555555555555555

View File

@@ -12,7 +12,7 @@ Table auc_2g contents:
algo_id_2g|ki|subscriber_id
1|BeefedCafeFaceAcedAddedDecadeFee|1
2|33333333333333333333333333333333|4
4|55555555555555555555555555555555|6
6|55555555555555555555555555555555|6
Table: auc_3g
name|type|notnull|dflt_value|pk
@@ -86,6 +86,7 @@ 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:
@@ -100,15 +101,15 @@ Table auc_2g contents:
algo_id_2g|ki|subscriber_id
1|BeefedCafeFaceAcedAddedDecadeFee|1
2|33333333333333333333333333333333|4
4|55555555555555555555555555555555|6
6|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(32)|1||0
op|VARCHAR(32)|0||0
opc|VARCHAR(32)|0||0
k|VARCHAR(64)|1||0
op|VARCHAR(64)|0||0
opc|VARCHAR(64)|0||0
sqn|INTEGER|1|0|0
subscriber_id|INTEGER|0||1
@@ -179,5 +180,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 6
DDB Database <PATH>test.db' has HLR DB schema version 7
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.

View File

@@ -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,4,'55555555555555555555555555555555');
INSERT INTO auc_2g VALUES(6,6,'55555555555555555555555555555555');
CREATE TABLE auc_3g (
subscriber_id INTEGER PRIMARY KEY, -- subscriber.id
algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value

View File

@@ -1,9 +1,9 @@
AM_CPPFLAGS = \
$(all_includes) \
-I$(top_srcdir)/include \
$(NULL)
AM_CFLAGS = \
-I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
$(NULL)

View File

@@ -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) \

View File

@@ -32,148 +32,6 @@ struct qname_enc_dec_test {
size_t qname_max_len; /* default: strlen(qname) + 1 */
};
static const struct qname_enc_dec_test qname_enc_dec_test_data[] = {
{
/* OK: typical mslookup domain */
.domain = "hlr.1234567.imsi",
.qname = "\x03" "hlr" "\x07" "1234567" "\x04" "imsi",
},
{
/* Wrong format: double dot */
.domain = "hlr..imsi",
.qname = NULL,
},
{
/* Wrong format: double dot */
.domain = "hlr",
.qname = "\x03hlr\0\x03imsi",
},
{
/* Wrong format: dot at end */
.domain = "hlr.",
.qname = NULL,
},
{
/* Wrong format: dot at start */
.domain = ".hlr",
.qname = NULL,
},
{
/* Wrong format: empty */
.domain = "",
.qname = NULL,
},
{
/* OK: maximum length */
.domain =
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"12345"
,
.qname =
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\x05" "12345"
},
{
/* Error: too long domain */
.domain =
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"123456789." "123456789." "123456789." "123456789." "123456789."
"12345toolong"
,
.qname = NULL,
},
{
/* Error: too long qname */
.domain = NULL,
.qname =
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
"\t123456789\t123456789\t123456789\t123456789\t123456789"
},
{
/* Error: wrong token length in qname */
.domain = NULL,
.qname = "\x03" "hlr" "\x07" "1234567" "\x05" "imsi",
},
{
/* Error: wrong token length in qname */
.domain = NULL,
.qname = "\x02" "hlr" "\x07" "1234567" "\x04" "imsi",
},
{
/* Wrong format: token length at end of qname */
.domain = NULL,
.qname = "\x03hlr\x03",
},
{
/* Error: overflow in label length */
.domain = NULL,
.qname = "\x03" "hlr" "\x07" "1234567" "\x04" "imsi",
.qname_max_len = 17,
},
};
void test_enc_dec_rfc_qname(void *ctx)
{
char quote_buf[300];
int i;
fprintf(stderr, "-- %s --\n", __func__);
for (i = 0; i < ARRAY_SIZE(qname_enc_dec_test_data); i++) {
const struct qname_enc_dec_test *t = &qname_enc_dec_test_data[i];
char *res;
if (t->domain) {
fprintf(stderr, "domain: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->domain, -1));
fprintf(stderr, "exp: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->qname, -1));
res = osmo_mdns_rfc_qname_encode(ctx, t->domain);
fprintf(stderr, "res: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), res, -1));
if (t->qname == res || (t->qname && res && strcmp(t->qname, res) == 0))
fprintf(stderr, "=> OK\n");
else
fprintf(stderr, "=> ERROR\n");
if (res)
talloc_free(res);
fprintf(stderr, "\n");
}
if (t->qname) {
size_t qname_max_len = t->qname_max_len;
if (qname_max_len)
fprintf(stderr, "qname_max_len: %lu\n", qname_max_len);
else
qname_max_len = strlen(t->qname) + 1;
fprintf(stderr, "qname: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->qname, -1));
fprintf(stderr, "exp: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->domain, -1));
res = osmo_mdns_rfc_qname_decode(ctx, t->qname, qname_max_len);
fprintf(stderr, "res: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), res, -1));
if (t->domain == res || (t->domain && res && strcmp(t->domain, res) == 0))
fprintf(stderr, "=> OK\n");
else
fprintf(stderr, "=> ERROR\n");
if (res)
talloc_free(res);
fprintf(stderr, "\n");
}
}
}
#define PRINT_HDR(hdr, name) \
fprintf(stderr, "header %s:\n" \
".id = %i\n" \
@@ -216,7 +74,7 @@ static const struct osmo_mdns_rfc_header header_enc_dec_test_data[] = {
},
};
void test_enc_dec_rfc_header()
void test_enc_dec_rfc_header(void)
{
int i;
@@ -241,7 +99,7 @@ void test_enc_dec_rfc_header()
}
}
void test_enc_dec_rfc_header_einval()
void test_enc_dec_rfc_header_einval(void)
{
struct osmo_mdns_rfc_header out = {0};
struct msgb *msg = msgb_alloc(4096, "dns_test");
@@ -289,7 +147,7 @@ void test_enc_dec_rfc_question(void *ctx)
struct msgb *msg = msgb_alloc(4096, "dns_test");
PRINT_QST(&in, "in");
assert(osmo_mdns_rfc_question_encode(ctx, msg, &in) == 0);
assert(osmo_mdns_rfc_question_encode(msg, &in) == 0);
fprintf(stderr, "encoded: %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
out = osmo_mdns_rfc_question_decode(ctx, msgb_data(msg), msgb_length(msg));
assert(out);
@@ -353,7 +211,7 @@ void test_enc_dec_rfc_record(void *ctx)
size_t record_len;
PRINT_REC(&in, "in");
assert(osmo_mdns_rfc_record_encode(ctx, msg, &in) == 0);
assert(osmo_mdns_rfc_record_encode(msg, &in) == 0);
fprintf(stderr, "encoded: %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
out = osmo_mdns_rfc_record_decode(ctx, msgb_data(msg), msgb_length(msg), &record_len);
fprintf(stderr, "record_len: %lu\n", record_len);
@@ -578,7 +436,7 @@ static void test_result_from_answer(void *ctx)
}
}
int main()
int main(int argc, char **argv)
{
void *ctx = talloc_named_const(NULL, 0, "main");
osmo_init_logging2(ctx, NULL);
@@ -589,7 +447,6 @@ int main()
log_set_print_category_hex(osmo_stderr_target, 0);
log_set_use_color(osmo_stderr_target, 0);
test_enc_dec_rfc_qname(ctx);
test_enc_dec_rfc_header();
test_enc_dec_rfc_header_einval();
test_enc_dec_rfc_question(ctx);

View File

@@ -1,85 +1,3 @@
-- test_enc_dec_rfc_qname --
domain: "hlr.1234567.imsi"
exp: "\3hlr\a1234567\4imsi"
res: "\3hlr\a1234567\4imsi"
=> OK
qname: "\3hlr\a1234567\4imsi"
exp: "hlr.1234567.imsi"
res: "hlr.1234567.imsi"
=> OK
domain: "hlr..imsi"
exp: NULL
res: NULL
=> OK
domain: "hlr"
exp: "\3hlr"
res: "\3hlr"
=> OK
qname: "\3hlr"
exp: "hlr"
res: "hlr"
=> OK
domain: "hlr."
exp: NULL
res: NULL
=> OK
domain: ".hlr"
exp: NULL
res: NULL
=> OK
domain: ""
exp: NULL
res: NULL
=> OK
domain: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345"
exp: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\512345"
res: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\512345"
=> OK
qname: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\512345"
exp: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345"
res: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345"
=> OK
domain: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345toolong"
exp: NULL
res: NULL
=> OK
qname: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\
exp: NULL
res: NULL
=> OK
qname: "\3hlr\a1234567\5imsi"
exp: NULL
res: NULL
=> OK
qname: "\2hlr\a1234567\4imsi"
exp: NULL
res: NULL
=> OK
qname: "\3hlr\3"
exp: NULL
res: NULL
=> OK
qname_max_len: 17
qname: "\3hlr\a1234567\4imsi"
exp: NULL
res: NULL
=> OK
-- test_enc_dec_rfc_header --
header in:
.id = 1337

View File

@@ -80,14 +80,14 @@ static int server_recv(struct osmo_fd *osmo_fd, unsigned int what)
return n;
}
static void server_init()
static void server_init(void)
{
fprintf(stderr, "%s\n", __func__);
server_mc = osmo_mdns_sock_init(ctx, TEST_IP, TEST_PORT, server_recv, NULL, 0);
OSMO_ASSERT(server_mc);
}
static void server_stop()
static void server_stop(void)
{
fprintf(stderr, "%s\n", __func__);
OSMO_ASSERT(server_mc);
@@ -98,7 +98,7 @@ static void server_stop()
struct osmo_mslookup_client* client;
struct osmo_mslookup_client_method* client_method;
static void client_init()
static void client_init(void)
{
fprintf(stderr, "%s\n", __func__);
client = osmo_mslookup_client_new(ctx);
@@ -117,7 +117,7 @@ static void client_recv(struct osmo_mslookup_client *client, uint32_t request_ha
osmo_mslookup_client_request_cancel(client, request_handle);
}
static void client_query()
static void client_query(void)
{
struct osmo_mslookup_id id = {.type = OSMO_MSLOOKUP_ID_IMSI,
.imsi = "123456789012345"};
@@ -134,7 +134,7 @@ static void client_query()
osmo_mslookup_client_request(client, &query, &handling);
}
static void client_stop()
static void client_stop(void)
{
fprintf(stderr, "%s\n", __func__);
osmo_mslookup_client_free(client);
@@ -154,7 +154,7 @@ const struct timeval fake_time_start_time = { 0, 0 };
osmo_timers_update(); \
} while (0)
static void fake_time_start()
static void fake_time_start(void)
{
struct timespec *clock_override;
@@ -167,7 +167,7 @@ static void fake_time_start()
osmo_clock_override_enable(CLOCK_MONOTONIC, true);
fake_time_passes(0, 0);
}
static void test_server_client()
static void test_server_client(void)
{
fprintf(stderr, "-- %s --\n", __func__);
server_init();
@@ -190,7 +190,7 @@ static void test_server_client()
client_stop();
}
bool is_multicast_enabled()
bool is_multicast_enabled(void)
{
bool ret = true;
struct addrinfo *ai;
@@ -222,7 +222,7 @@ bool is_multicast_enabled()
/*
* Run all tests
*/
int main()
int main(int argc, char **argv)
{
if (!is_multicast_enabled()) {
fprintf(stderr, "ERROR: multicast is disabled! (OS#4361)");

View File

@@ -147,7 +147,7 @@ const struct timeval fake_time_start_time = { 0, 0 };
osmo_timers_update(); \
} while (0)
static void fake_time_start()
static void fake_time_start(void)
{
struct timespec *clock_override;
@@ -169,7 +169,7 @@ static void result_cb_once(struct osmo_mslookup_client *client,
LOGP(DMSLOOKUP, LOGL_DEBUG, "result_cb(): %s\n", osmo_mslookup_result_name_c(ctx, query, result));
}
int main()
int main(int argc, char **argv)
{
ctx = talloc_named_const(NULL, 0, "main");
osmo_init_logging2(ctx, NULL);

View File

@@ -50,7 +50,7 @@ const char *domains[] = {
"qwerty.1.qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmm",
};
void test_osmo_mslookup_query_init_from_domain_str()
void test_osmo_mslookup_query_init_from_domain_str(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(domains); i++) {
@@ -68,7 +68,7 @@ void test_osmo_mslookup_query_init_from_domain_str()
}
}
int main()
int main(int argc, char **argv)
{
ctx = talloc_named_const(NULL, 0, "main");
osmo_init_logging2(ctx, NULL);

View File

@@ -47,11 +47,13 @@ OsmoHLR(config-hlr)# ?
no Negate a command or set its defaults
ussd USSD Configuration
ncss-guard-timeout Set guard timer for NCSS (call independent SS) session activity
reject-cause GSUP/GMM cause to be sent
store-imei Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send Check IMEI requests (for OsmoMSC, you may want to set 'check-imei-rqd 1').
subscriber-create-on-demand Make a new record when a subscriber is first seen.
OsmoHLR(config-hlr)# list
...
gsup
ps
database PATH
euse NAME
no euse NAME
@@ -61,6 +63,7 @@ OsmoHLR(config-hlr)# list
ussd default-route external EUSE
no ussd default-route
ncss-guard-timeout <0-255>
reject-cause (not-found|no-proxy) (imsi-unknown|illegal-ms|plmn-not-allowed|la-not-allowed|roaming-not-allowed|no-suitable-cell-in-la|net-fail|congestion|auth-unacceptable|proto-error-unspec)
store-imei
no store-imei
subscriber-create-on-demand (no-msisdn|<3-15>) (none|cs|ps|cs+ps)
@@ -110,6 +113,12 @@ 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
@@ -349,15 +358,15 @@ mslookup
service foo.bar at 123.45.67.89 1011
service baz.bar at 121.31.41.5 1617
service baz.bar at a:b:c::d 1819
msc MSC-1
msc msc-901-70-23
service foo.bar at 76.54.32.10 1234
service baz.bar at 12.11.10.98 7654
service baz.bar at dd:cc:bb::a 3210
msc msc-901-70-42
service foo.bar at 1.1.1.1 1111
service baz.bar at 2.2.2.2 2222
service baz.bar at 2222:2222:2222::2 2222
msc ipa-name MSC-1
msc ipa-name msc-901-70-23
service foo.bar at 76.54.32.10 1234
service baz.bar at 12.11.10.98 7654
service baz.bar at dd:cc:bb::a 3210
msc ipa-name msc-901-70-42
service foo.bar at 1.1.1.1 1111
service baz.bar at 2.2.2.2 2222
service baz.bar at 2222:2222:2222::2 2222
client
gateway-proxy 1.2.3.4 4222
mdns bind 239.192.23.42 4266
@@ -404,12 +413,12 @@ mslookup
mdns bind 239.192.23.42 4266
service foo.bar at 123.45.67.89 1011
service baz.bar at 121.31.41.5 1617
msc MSC-1
msc msc-901-70-23
service foo.bar at 76.54.32.10 1234
service baz.bar at 12.11.10.98 7654
msc msc-901-70-42
service foo.bar at 1.1.1.1 1111
msc ipa-name MSC-1
msc ipa-name msc-901-70-23
service foo.bar at 76.54.32.10 1234
service baz.bar at 12.11.10.98 7654
msc ipa-name msc-901-70-42
service foo.bar at 1.1.1.1 1111
client
mdns bind 239.192.23.42 4266
...
@@ -437,12 +446,53 @@ mslookup
service foo.bar at 123.45.67.89 1011
service baz.bar at 121.31.41.5 1617
service gsup.hlr at 23.42.17.11 4223
msc MSC-1
msc msc-901-70-23
service foo.bar at 76.54.32.10 1234
service baz.bar at 12.11.10.98 7654
msc msc-901-70-42
service foo.bar at 1.1.1.1 1111
msc ipa-name MSC-1
msc ipa-name msc-901-70-23
service foo.bar at 76.54.32.10 1234
service baz.bar at 12.11.10.98 7654
msc ipa-name msc-901-70-42
service foo.bar at 1.1.1.1 1111
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 *
...

View File

@@ -674,11 +674,11 @@ 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,c01ffedc1cadaeac1d1f1edacac1ab0a
SET 113 subscriber.by-imsi-901991234567891.aud2g xor-2g,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,c01ffedc1cadaeac1d1f1edacac1ab0a
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

View File

@@ -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) ki KI
subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor-2g) ki KI
subscriber (imsi|msisdn|id|imei) IDENT update aud3g none
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 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 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 Use XOR algorithm
xor-2g Use XOR-2G 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 ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d
OsmoHLR# subscriber imsi 123456789023000 update aud2g xor-2g ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d
OsmoHLR# subscriber imsi 123456789023000 show
ID: 101
IMSI: 123456789023000
MSISDN: 423
2G auth: XOR
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 ki CoiffedCicadaeAcidifiedAcaciaBoa
OsmoHLR# subscriber id 101 update aud2g xor-2g 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 ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX
OsmoHLR# subscriber id 101 update aud2g xor-2g ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX
% Invalid value for KI: 'C01ffedC1cadaeAc1d1f1edAcac1aB0aX'
OsmoHLR# subscriber id 101 show
ID: 101
@@ -269,20 +269,21 @@ OsmoHLR# subscriber id 101 show
OsmoHLR# subscriber imsi 123456789023000 update aud3g ?
none Delete 3G authentication data
milenage Use Milenage algorithm
xor Use XOR algorithm
tuak Use TUAK algorithm
xor-3g Use XOR-3G 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 hexadecimal characters
K K as 32/64 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 hexadecimal characters
OP_C OP or OPC as 32/64 hexadecimal characters
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc CededEffacedAceFacedBadFadedBeef ?
[ind-bitlen] Set IND bit length

View File

@@ -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,2134
SET 56 subscriber.by-imsi-901990000000003.aud2g xor-2g,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 60 subscriber.by-imsi-901990000000003.aud3g milenage,2134
ERROR 60 Invalid KI.
SET 59 subscriber.by-imsi-901990000000003.aud3g milenage,2134
ERROR 59 Invalid KI.
SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA
SET 60 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA
ERROR 60 Invalid format.
SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
ERROR 61 Invalid format.
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
ERROR 62 Invalid format.
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz
ERROR 62 Invalid OP/OPC.
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.
SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,
ERROR 63 Invalid format.