blob: bdf139381d5425dae4a6c81c9a9cc5afef65933c [file] [log] [blame]
Neels Hofmeyr98509462017-10-09 17:28:53 +02001/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
2 * All Rights Reserved
3 *
4 * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <stdio.h>
22#include <errno.h>
23#include <getopt.h>
24#include <inttypes.h>
25
26#include <osmocom/core/application.h>
27#include <osmocom/core/utils.h>
28#include <osmocom/core/logging.h>
29
Neels Hofmeyrc79bcde2019-12-04 01:04:32 +010030#include <osmocom/gsupclient/cni_peer_id.h>
Neels Hofmeyr2f758032019-11-20 00:37:07 +010031#include <osmocom/hlr/db.h>
32#include <osmocom/hlr/logging.h>
Neels Hofmeyr98509462017-10-09 17:28:53 +020033
34#define comment_start() fprintf(stderr, "\n===== %s\n", __func__);
35#define comment(fmt, args...) fprintf(stderr, "\n--- " fmt "\n\n", ## args);
36#define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__);
37
Neels Hofmeyrb6837e32017-10-10 23:20:26 +020038#define fill_invalid(x) _fill_invalid(&x, sizeof(x))
39static void _fill_invalid(void *dest, size_t size)
40{
41 uint8_t *pos = dest;
42 size_t remain = size;
43 int wrote = 0;
44 do {
45 remain -= wrote;
46 pos += wrote;
47 wrote = snprintf((void*)pos, remain, "-invalid-data");
48 } while (wrote < remain);
49}
50
Neels Hofmeyr98509462017-10-09 17:28:53 +020051/* Perform a function call and verbosely assert that its return value is as expected.
52 * The return code is then available in g_rc. */
53#define ASSERT_RC(call, expect_rc) \
54 do { \
Ruben Undheim8b860e52018-11-16 08:47:26 +010055 if ((expect_rc) == -ENOKEY) \
56 fprintf(stderr, #call " --> -ENOKEY\n"); \
57 else if ((expect_rc) == -ENOTSUP) \
58 fprintf(stderr, #call " --> -ENOTSUP\n"); \
59 else \
60 fprintf(stderr, #call " --> " #expect_rc "\n"); \
Neels Hofmeyr98509462017-10-09 17:28:53 +020061 g_rc = call; \
62 if (g_rc != (expect_rc)) \
63 fprintf(stderr, " MISMATCH: got rc = %d, expected: " \
64 #expect_rc " = %d\n", g_rc, expect_rc); \
65 OSMO_ASSERT(g_rc == (expect_rc)); \
66 fprintf(stderr, "\n"); \
67 } while (0)
68
69/* Do db_subscr_get_by_xxxx and verbosely assert that its return value is as expected.
70 * Print the subscriber struct to stderr to be validated by db_test.err.
71 * The result is then available in g_subscr. */
72#define ASSERT_SEL(by, val, expect_rc) \
73 do { \
74 int rc; \
Neels Hofmeyrb6837e32017-10-10 23:20:26 +020075 fill_invalid(g_subscr); \
Ruben Undheim8b860e52018-11-16 08:47:26 +010076 if ((expect_rc) == -ENOKEY) \
77 fprintf(stderr, "db_subscr_get_by_" #by "(dbc, " #val ", &g_subscr) --> -ENOKEY \n"); \
78 else if ((expect_rc) == -ENOTSUP) \
79 fprintf(stderr, "db_subscr_get_by_" #by "(dbc, " #val ", &g_subscr) --> -ENOTSUP \n"); \
80 else \
81 fprintf(stderr, "db_subscr_get_by_" #by "(dbc, " #val ", &g_subscr) --> " \
Neels Hofmeyr98509462017-10-09 17:28:53 +020082 #expect_rc "\n"); \
83 rc = db_subscr_get_by_##by(dbc, val, &g_subscr); \
84 if (rc != (expect_rc)) \
85 fprintf(stderr, " MISMATCH: got rc = %d, expected: " \
86 #expect_rc " = %d\n", rc, expect_rc); \
87 OSMO_ASSERT(rc == (expect_rc)); \
88 if (!rc) \
89 dump_subscr(&g_subscr); \
90 fprintf(stderr, "\n"); \
91 } while (0)
92
Neels Hofmeyr1332a172017-10-10 02:25:00 +020093/* Do db_get_auth_data() and verbosely assert that its return value is as expected.
94 * Print the subscriber struct to stderr to be validated by db_test.err.
95 * The results are then available in g_aud2g and g_aud3g. */
96#define ASSERT_SEL_AUD(imsi, expect_rc, expect_id) \
97 do { \
Neels Hofmeyrb6837e32017-10-10 23:20:26 +020098 fill_invalid(g_aud2g); \
99 fill_invalid(g_aud3g); \
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200100 g_id = 0; \
101 ASSERT_RC(db_get_auth_data(dbc, imsi, &g_aud2g, &g_aud3g, &g_id), expect_rc); \
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200102 if (!g_rc) { \
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200103 dump_aud("2G", &g_aud2g); \
104 dump_aud("3G", &g_aud3g); \
105 }\
106 if (g_id != expect_id) {\
107 fprintf(stderr, "MISMATCH: got subscriber id %"PRId64 \
108 ", expected %"PRId64"\n", g_id, (int64_t)(expect_id)); \
109 OSMO_ASSERT(g_id == expect_id); \
110 } \
111 fprintf(stderr, "\n"); \
112 } while (0)
113
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100114#define N_VECTORS 3
115
116#define ASSERT_DB_GET_AUC(imsi, expect_rc) \
117 do { \
118 struct osmo_auth_vector vec[N_VECTORS]; \
Harald Welte06f5af22019-08-21 20:01:31 +0200119 ASSERT_RC(db_get_auc(dbc, imsi, 3, vec, N_VECTORS, NULL, NULL, false), expect_rc); \
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100120 } while (0)
121
122/* Not linking the real auc_compute_vectors(), just returning num_vec.
123 * This gets called by db_get_auc(), but we're only interested in its rc. */
124int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
Harald Weltea854b482023-05-30 17:27:32 +0200125 struct osmo_sub_auth_data2 *aud2g,
126 struct osmo_sub_auth_data2 *aud3g,
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100127 const uint8_t *rand_auts, const uint8_t *auts)
128{ return num_vec; }
129
Neels Hofmeyr98509462017-10-09 17:28:53 +0200130static struct db_context *dbc = NULL;
131static void *ctx = NULL;
132static struct hlr_subscriber g_subscr;
Harald Weltea854b482023-05-30 17:27:32 +0200133static struct osmo_sub_auth_data2 g_aud2g;
134static struct osmo_sub_auth_data2 g_aud3g;
Neels Hofmeyr98509462017-10-09 17:28:53 +0200135static int g_rc;
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200136static int64_t g_id;
Neels Hofmeyr98509462017-10-09 17:28:53 +0200137
138#define Pfv(name, fmt, val) \
139 fprintf(stderr, " ." #name " = " fmt ",\n", val)
140#define Pfo(name, fmt, obj) \
141 Pfv(name, fmt, obj->name)
142
143/* Print a subscriber struct to stderr to be validated by db_test.err. */
144void dump_subscr(struct hlr_subscriber *subscr)
145{
146#define Ps(name) \
147 if (*subscr->name) \
148 Pfo(name, "'%s'", subscr)
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100149#define Pgt(name) \
150 Pfv(name, "%s", osmo_ipa_name_to_str(&subscr->name))
Neels Hofmeyr98509462017-10-09 17:28:53 +0200151#define Pd(name) \
152 Pfv(name, "%"PRId64, (int64_t)subscr->name)
153#define Pd_nonzero(name) \
154 if (subscr->name) \
155 Pd(name)
156#define Pb(if_val, name) \
157 if (subscr->name == (if_val)) \
158 Pfv(name, "%s", subscr->name ? "true" : "false")
159
160 fprintf(stderr, "struct hlr_subscriber {\n");
161 Pd(id);
162 Ps(imsi);
163 Ps(msisdn);
Oliver Smith81db3892019-01-09 12:03:51 +0100164 Ps(imei);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200165 Ps(vlr_number);
166 Ps(sgsn_number);
167 Ps(sgsn_address);
168 Pd_nonzero(periodic_lu_timer);
169 Pd_nonzero(periodic_rau_tau_timer);
170 Pb(false, nam_cs);
171 Pb(false, nam_ps);
172 if (subscr->lmsi)
173 Pfo(lmsi, "0x%x", subscr);
174 Pb(true, ms_purged_cs);
175 Pb(true, ms_purged_ps);
176 fprintf(stderr, "}\n");
177#undef Ps
178#undef Pd
179#undef Pd_nonzero
180#undef Pb
181}
182
Harald Weltea854b482023-05-30 17:27:32 +0200183void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
Neels Hofmeyr98509462017-10-09 17:28:53 +0200184{
185 if (aud->type == OSMO_AUTH_TYPE_NONE) {
186 fprintf(stderr, "%s: none\n", label);
187 return;
188 }
189
Harald Weltea854b482023-05-30 17:27:32 +0200190 fprintf(stderr, "%s: struct osmo_sub_auth_data2 {\n", label);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200191#define Pf(name, fmt) \
192 Pfo(name, fmt, aud)
193#define Phex(name) \
194 Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name)))
Harald Weltea854b482023-05-30 17:27:32 +0200195#define Phexl(name, len) \
196 Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, aud->len))
197
Neels Hofmeyr98509462017-10-09 17:28:53 +0200198
199 Pfv(type, "%s", osmo_sub_auth_type_name(aud->type));
200 Pfv(algo, "%s", osmo_auth_alg_name(aud->algo));
201 switch (aud->type) {
202 case OSMO_AUTH_TYPE_GSM:
203 Phex(u.gsm.ki);
204 break;
205 case OSMO_AUTH_TYPE_UMTS:
Harald Weltea854b482023-05-30 17:27:32 +0200206 Phexl(u.umts.opc, u.umts.opc_len);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200207 Pf(u.umts.opc_is_op, "%u");
Harald Weltea854b482023-05-30 17:27:32 +0200208 Phexl(u.umts.k, u.umts.k_len);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200209 Phex(u.umts.amf);
210 if (aud->u.umts.sqn) {
211 Pf(u.umts.sqn, "%"PRIu64);
212 Pf(u.umts.sqn, "0x%"PRIx64);
213 }
214 if (aud->u.umts.ind_bitlen)
215 Pf(u.umts.ind_bitlen, "%u");
216 break;
217 default:
218 OSMO_ASSERT(false);
219 }
220
221 fprintf(stderr, "}\n");
222
223#undef Pf
224#undef Phex
Harald Weltea854b482023-05-30 17:27:32 +0200225#undef Phexl
Neels Hofmeyr98509462017-10-09 17:28:53 +0200226}
227
Oliver Smith6401b902019-07-24 11:32:45 +0200228void db_raw_sql(struct db_context *dbc, const char *sql)
229{
230 sqlite3_stmt *stmt;
231
232 fprintf(stderr, "raw SQL: %s\n", sql);
233 ASSERT_RC(sqlite3_prepare_v2(dbc->db, sql, -1, &stmt, NULL), SQLITE_OK);
234 ASSERT_RC(sqlite3_step(stmt), SQLITE_DONE);
235 db_remove_reset(stmt);
236 sqlite3_finalize(stmt);
237}
238
Neels Hofmeyr98509462017-10-09 17:28:53 +0200239static const char *imsi0 = "123456789000000";
240static const char *imsi1 = "123456789000001";
241static const char *imsi2 = "123456789000002";
242static const char *short_imsi = "123456";
243static const char *unknown_imsi = "999999999";
244
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100245static int db_subscr_lu_str(struct db_context *dbc, int64_t subscr_id,
246 const char *vlr_or_sgsn_number, bool is_ps)
247{
248 struct osmo_ipa_name vlr_nr;
249 osmo_ipa_name_set_str(&vlr_nr, vlr_or_sgsn_number);
250 return db_subscr_lu(dbc, subscr_id, &vlr_nr, is_ps, NULL);
251}
252
Harald Welte7a476532022-11-03 11:38:41 +0100253static void test_subscr_create_update_sel_delete(void)
Neels Hofmeyr98509462017-10-09 17:28:53 +0200254{
255 int64_t id0, id1, id2, id_short;
256 comment_start();
257
258 comment("Create with valid / invalid IMSI");
259
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100260 ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200261 ASSERT_SEL(imsi, imsi0, 0);
262 id0 = g_subscr.id;
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100263 ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200264 ASSERT_SEL(imsi, imsi1, 0);
265 id1 = g_subscr.id;
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100266 ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200267 ASSERT_SEL(imsi, imsi2, 0);
268 id2 = g_subscr.id;
Pau Espin Pedrold456fce2022-06-17 17:56:56 +0200269 ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200270 ASSERT_SEL(imsi, imsi0, 0);
Pau Espin Pedrold456fce2022-06-17 17:56:56 +0200271 ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
272 ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200273 ASSERT_SEL(imsi, imsi1, 0);
Pau Espin Pedrold456fce2022-06-17 17:56:56 +0200274 ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
275 ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200276 ASSERT_SEL(imsi, imsi2, 0);
277
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100278 ASSERT_RC(db_subscr_create(dbc, "123456789 000003", DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200279 ASSERT_SEL(imsi, "123456789000003", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200280
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100281 ASSERT_RC(db_subscr_create(dbc, "123456789000002123456", DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS),
282 -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200283 ASSERT_SEL(imsi, "123456789000002123456", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200284
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100285 ASSERT_RC(db_subscr_create(dbc, "foobar123", DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200286 ASSERT_SEL(imsi, "foobar123", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200287
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100288 ASSERT_RC(db_subscr_create(dbc, "123", DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200289 ASSERT_SEL(imsi, "123", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200290
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100291 ASSERT_RC(db_subscr_create(dbc, short_imsi, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200292 ASSERT_SEL(imsi, short_imsi, 0);
293 id_short = g_subscr.id;
294
Oliver Smith6b73fd92019-03-06 13:49:05 +0100295 comment("Check if subscriber exists (by IMSI)");
296
297 ASSERT_RC(db_subscr_exists_by_imsi(dbc, imsi0), 0);
298 ASSERT_RC(db_subscr_exists_by_imsi(dbc, unknown_imsi), -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200299
300 comment("Set valid / invalid MSISDN");
301
302 ASSERT_SEL(imsi, imsi0, 0);
303 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0, "54321"), 0);
304 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200305 ASSERT_SEL(msisdn, "54321", 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200306 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
307 "54321012345678912345678"), -EINVAL);
308 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200309 ASSERT_SEL(msisdn, "54321", 0);
310 ASSERT_SEL(msisdn, "54321012345678912345678", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200311 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
312 "543 21"), -EINVAL);
313 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200314 ASSERT_SEL(msisdn, "543 21", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200315 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
316 "foobar123"), -EINVAL);
317 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200318 ASSERT_SEL(msisdn, "foobar123", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200319 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
320 "5"), 0);
321 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200322 ASSERT_SEL(msisdn, "5", 0);
323 ASSERT_SEL(msisdn, "54321", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200324 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
325 "543210123456789"), 0);
326 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200327 ASSERT_SEL(msisdn, "543210123456789", 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200328 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
329 "5432101234567891"), -EINVAL);
330 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200331 ASSERT_SEL(msisdn, "5432101234567891", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200332
Vadim Yanitskiyc13599d2019-03-30 17:03:42 +0700333 comment("Check if subscriber exists (by MSISDN)");
334
335 ASSERT_RC(db_subscr_exists_by_msisdn(dbc, "543210123456789"), 0);
336 ASSERT_RC(db_subscr_exists_by_msisdn(dbc, "5432101234567891"), -ENOENT);
337
Neels Hofmeyr98509462017-10-09 17:28:53 +0200338 comment("Set MSISDN on non-existent / invalid IMSI");
339
340 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, unknown_imsi, "99"), -ENOENT);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200341 ASSERT_SEL(msisdn, "99", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200342
343 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, "foobar", "99"), -ENOENT);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200344 ASSERT_SEL(msisdn, "99", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200345
Oliver Smith81db3892019-01-09 12:03:51 +0100346 comment("Set valid / invalid IMEI");
347
348 ASSERT_RC(db_subscr_update_imei_by_imsi(dbc, imsi0, "12345678901234"), 0);
349 ASSERT_SEL(imei, "12345678901234", 0);
350
351 ASSERT_RC(db_subscr_update_imei_by_imsi(dbc, imsi0, "123456789012345"), -EINVAL); /* too long */
352 ASSERT_SEL(imei, "12345678901234", 0);
353 ASSERT_SEL(imei, "123456789012345", -ENOENT);
354
355 comment("Set the same IMEI again");
356 ASSERT_RC(db_subscr_update_imei_by_imsi(dbc, imsi0, "12345678901234"), 0);
357 ASSERT_SEL(imei, "12345678901234", 0);
358
359 comment("Remove IMEI");
360 ASSERT_RC(db_subscr_update_imei_by_imsi(dbc, imsi0, NULL), 0);
361 ASSERT_SEL(imei, "12345678901234", -ENOENT);
362
Neels Hofmeyre8ccd502017-10-06 04:10:06 +0200363 comment("Set / unset nam_cs and nam_ps");
364
365 /* nam_val, is_ps */
366 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, true), 0);
367 ASSERT_SEL(imsi, imsi0, 0);
368 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, false), 0);
369 ASSERT_SEL(imsi, imsi0, 0);
370 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, false), 0);
371 ASSERT_SEL(imsi, imsi0, 0);
372 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, true), 0);
373 ASSERT_SEL(imsi, imsi0, 0);
374
375 comment("Set / unset nam_cs and nam_ps *again*");
376 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, true), 0);
377 ASSERT_SEL(imsi, imsi0, 0);
378 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, true), 0);
379 ASSERT_SEL(imsi, imsi0, 0);
380 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, false), 0);
381 ASSERT_SEL(imsi, imsi0, 0);
382 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, false), 0);
383 ASSERT_SEL(imsi, imsi0, 0);
384 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, true), 0);
385 ASSERT_SEL(imsi, imsi0, 0);
386 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, true), 0);
387 ASSERT_SEL(imsi, imsi0, 0);
388 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, false), 0);
389 ASSERT_SEL(imsi, imsi0, 0);
390 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, false), 0);
391 ASSERT_SEL(imsi, imsi0, 0);
392
393 comment("Set nam_cs and nam_ps on non-existent / invalid IMSI");
394
395 ASSERT_RC(db_subscr_nam(dbc, unknown_imsi, false, true), -ENOENT);
396 ASSERT_RC(db_subscr_nam(dbc, unknown_imsi, false, false), -ENOENT);
397 ASSERT_SEL(imsi, unknown_imsi, -ENOENT);
398
399 ASSERT_RC(db_subscr_nam(dbc, "foobar", false, true), -ENOENT);
400 ASSERT_RC(db_subscr_nam(dbc, "foobar", false, false), -ENOENT);
401
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200402 comment("Record LU for PS and CS (SGSN and VLR names)");
403
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100404 ASSERT_RC(db_subscr_lu_str(dbc, id0, "5952", true), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200405 ASSERT_SEL(id, id0, 0);
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100406 ASSERT_RC(db_subscr_lu_str(dbc, id0, "712", false), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200407 ASSERT_SEL(id, id0, 0);
408
409 comment("Record LU for PS and CS (SGSN and VLR names) *again*");
410
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100411 ASSERT_RC(db_subscr_lu_str(dbc, id0, "111", true), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200412 ASSERT_SEL(id, id0, 0);
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100413 ASSERT_RC(db_subscr_lu_str(dbc, id0, "111", true), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200414 ASSERT_SEL(id, id0, 0);
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100415 ASSERT_RC(db_subscr_lu_str(dbc, id0, "222", false), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200416 ASSERT_SEL(id, id0, 0);
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100417 ASSERT_RC(db_subscr_lu_str(dbc, id0, "222", false), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200418 ASSERT_SEL(id, id0, 0);
419
420 comment("Unset LU info for PS and CS (SGSN and VLR names)");
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100421 ASSERT_RC(db_subscr_lu_str(dbc, id0, "", true), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200422 ASSERT_SEL(id, id0, 0);
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100423 ASSERT_RC(db_subscr_lu_str(dbc, id0, "", false), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200424 ASSERT_SEL(id, id0, 0);
425
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100426 ASSERT_RC(db_subscr_lu_str(dbc, id0, "111", true), 0);
427 ASSERT_RC(db_subscr_lu_str(dbc, id0, "222", false), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200428 ASSERT_SEL(id, id0, 0);
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100429 ASSERT_RC(db_subscr_lu_str(dbc, id0, NULL, true), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200430 ASSERT_SEL(id, id0, 0);
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100431 ASSERT_RC(db_subscr_lu_str(dbc, id0, NULL, false), 0);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200432 ASSERT_SEL(id, id0, 0);
433
434 comment("Record LU for non-existent ID");
Neels Hofmeyrad868e22019-11-20 02:36:45 +0100435 ASSERT_RC(db_subscr_lu_str(dbc, 99999, "5952", true), -ENOENT);
436 ASSERT_RC(db_subscr_lu_str(dbc, 99999, "712", false), -ENOENT);
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200437 ASSERT_SEL(id, 99999, -ENOENT);
438
Neels Hofmeyre50121e2017-10-09 17:48:51 +0200439 comment("Purge and un-purge PS and CS");
440
441 /* purge_val, is_ps */
442 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, true), 0);
443 ASSERT_SEL(imsi, imsi0, 0);
444 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, false), 0);
445 ASSERT_SEL(imsi, imsi0, 0);
446 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, false), 0);
447 ASSERT_SEL(imsi, imsi0, 0);
448 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, true), 0);
449 ASSERT_SEL(imsi, imsi0, 0);
450
451 comment("Purge PS and CS *again*");
452
453 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, true), 0);
454 ASSERT_SEL(imsi, imsi0, 0);
455 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, true), 0);
456 ASSERT_SEL(imsi, imsi0, 0);
457 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, true), 0);
458 ASSERT_SEL(imsi, imsi0, 0);
459 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, true), 0);
460 ASSERT_SEL(imsi, imsi0, 0);
461 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, false), 0);
462 ASSERT_SEL(imsi, imsi0, 0);
463 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, false), 0);
464 ASSERT_SEL(imsi, imsi0, 0);
465 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, false), 0);
466 ASSERT_SEL(imsi, imsi0, 0);
467 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, false), 0);
468 ASSERT_SEL(imsi, imsi0, 0);
469
470 comment("Purge on non-existent / invalid IMSI");
471
472 ASSERT_RC(db_subscr_purge(dbc, unknown_imsi, true, true), -ENOENT);
473 ASSERT_SEL(imsi, unknown_imsi, -ENOENT);
474 ASSERT_RC(db_subscr_purge(dbc, unknown_imsi, true, false), -ENOENT);
475 ASSERT_SEL(imsi, unknown_imsi, -ENOENT);
476
Neels Hofmeyr98509462017-10-09 17:28:53 +0200477 comment("Delete non-existent / invalid IDs");
478
479 ASSERT_RC(db_subscr_delete_by_id(dbc, 999), -ENOENT);
480 ASSERT_RC(db_subscr_delete_by_id(dbc, -10), -ENOENT);
481
482 comment("Delete subscribers");
483
484 ASSERT_SEL(imsi, imsi0, 0);
485 ASSERT_RC(db_subscr_delete_by_id(dbc, id0), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200486 ASSERT_SEL(imsi, imsi0, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200487 ASSERT_RC(db_subscr_delete_by_id(dbc, id0), -ENOENT);
488
489 ASSERT_SEL(imsi, imsi1, 0);
490 ASSERT_RC(db_subscr_delete_by_id(dbc, id1), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200491 ASSERT_SEL(imsi, imsi1, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200492
493 ASSERT_SEL(imsi, imsi2, 0);
494 ASSERT_RC(db_subscr_delete_by_id(dbc, id2), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200495 ASSERT_SEL(imsi, imsi2, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200496
497 ASSERT_SEL(imsi, short_imsi, 0);
498 ASSERT_RC(db_subscr_delete_by_id(dbc, id_short), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200499 ASSERT_SEL(imsi, short_imsi, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200500
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100501 comment("Create and delete subscribers with non-default nam_cs and nam_ps");
502
503 ASSERT_RC(db_subscr_create(dbc, imsi0, 0x00), 0);
504 ASSERT_SEL(imsi, imsi0, 0);
505 id0 = g_subscr.id;
506 ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS), 0);
507 ASSERT_SEL(imsi, imsi1, 0);
508 id1 = g_subscr.id;
509 ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_PS), 0);
510 ASSERT_SEL(imsi, imsi2, 0);
511 id2 = g_subscr.id;
512
513 ASSERT_RC(db_subscr_delete_by_id(dbc, id0), 0);
514 ASSERT_RC(db_subscr_delete_by_id(dbc, id1), 0);
515 ASSERT_RC(db_subscr_delete_by_id(dbc, id2), 0);
516
Neels Hofmeyr98509462017-10-09 17:28:53 +0200517 comment_end();
518}
519
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200520static const struct sub_auth_data_str *mk_aud_2g(enum osmo_auth_algo algo,
521 const char *ki)
522{
523 static struct sub_auth_data_str aud;
524 aud = (struct sub_auth_data_str){
525 .type = OSMO_AUTH_TYPE_GSM,
526 .algo = algo,
527 .u.gsm.ki = ki,
528 };
529 return &aud;
530}
531
532static const struct sub_auth_data_str *mk_aud_3g(enum osmo_auth_algo algo,
533 const char *opc, bool opc_is_op,
534 const char *k, unsigned int ind_bitlen)
535{
536 static struct sub_auth_data_str aud;
537 aud = (struct sub_auth_data_str){
538 .type = OSMO_AUTH_TYPE_UMTS,
539 .algo = algo,
540 .u.umts.k = k,
541 .u.umts.opc = opc,
542 .u.umts.opc_is_op = opc_is_op ? 1 : 0,
543 .u.umts.ind_bitlen = ind_bitlen,
544 };
545 return &aud;
546}
547
Harald Welte7a476532022-11-03 11:38:41 +0100548static void test_subscr_aud(void)
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200549{
550 int64_t id;
551
552 comment_start();
553
554 comment("Get auth data for non-existent subscriber");
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200555 ASSERT_SEL_AUD(unknown_imsi, -ENOENT, 0);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100556 ASSERT_DB_GET_AUC(imsi0, -ENOENT);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200557
558 comment("Create subscriber");
559
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100560 ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200561 ASSERT_SEL(imsi, imsi0, 0);
562
563 id = g_subscr.id;
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100564 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100565 ASSERT_DB_GET_AUC(imsi0, -ENOKEY);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200566
567
568 comment("Set auth data, 2G only");
569
570 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
571 mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "0123456789abcdef0123456789abcdef")),
572 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200573 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100574 ASSERT_DB_GET_AUC(imsi0, N_VECTORS);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200575
576 /* same again */
577 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
578 mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "0123456789abcdef0123456789abcdef")),
579 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200580 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200581
582 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
583 mk_aud_2g(OSMO_AUTH_ALG_COMP128v2, "BeadedBeeAced1EbbedDefacedFacade")),
584 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200585 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200586
587 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
588 mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "DeafBeddedBabeAcceededFadedDecaf")),
589 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200590 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200591
592 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
Harald Welte829713a2023-05-30 16:57:27 +0200593 mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200594 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200595 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200596
597 comment("Remove 2G auth data");
598
599 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
600 mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)),
601 0);
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100602 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100603 ASSERT_DB_GET_AUC(imsi0, -ENOKEY);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200604
605 /* Removing nothing results in -ENOENT */
606 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
607 mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)),
608 -ENOENT);
609
610 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
Harald Welte829713a2023-05-30 16:57:27 +0200611 mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200612 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200613 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200614
615 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
616 mk_aud_2g(OSMO_AUTH_ALG_NONE, "f000000000000f00000000000f000000")),
617 0);
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100618 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100619 ASSERT_DB_GET_AUC(imsi0, -ENOKEY);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200620
621
622 comment("Set auth data, 3G only");
623
624 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
625 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
626 "BeefedCafeFaceAcedAddedDecadeFee", true,
627 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
628 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200629 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100630 ASSERT_DB_GET_AUC(imsi0, N_VECTORS);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200631
632 /* same again */
633 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
634 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
635 "BeefedCafeFaceAcedAddedDecadeFee", true,
636 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
637 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200638 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200639
640 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
641 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
642 "Deaf0ff1ceD0d0DabbedD1ced1ceF00d", true,
643 "F1bbed0afD0eF0bD0ffed0ddF1fe0b0e", 0)),
644 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200645 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200646
647 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
648 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
649 "BeefedCafeFaceAcedAddedDecadeFee", false,
650 "DeafBeddedBabeAcceededFadedDecaf",
651 OSMO_MILENAGE_IND_BITLEN_MAX)),
652 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200653 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200654
655 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
656 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
657 "CededEffacedAceFacedBadFadedBeef", false,
658 "BeefedCafeFaceAcedAddedDecadeFee", 5)),
659 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200660 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200661
662 comment("Remove 3G auth data");
663
664 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
665 mk_aud_3g(OSMO_AUTH_ALG_NONE, NULL, false, NULL, 0)),
666 0);
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100667 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100668 ASSERT_DB_GET_AUC(imsi0, -ENOKEY);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200669
670 /* Removing nothing results in -ENOENT */
671 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
672 mk_aud_3g(OSMO_AUTH_ALG_NONE, NULL, false, NULL, 0)),
673 -ENOENT);
674
675 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
676 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
677 "CededEffacedAceFacedBadFadedBeef", false,
678 "BeefedCafeFaceAcedAddedDecadeFee", 5)),
679 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200680 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100681 ASSERT_DB_GET_AUC(imsi0, N_VECTORS);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200682
683 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
684 mk_aud_3g(OSMO_AUTH_ALG_NONE,
685 "asdfasdfasd", false,
686 "asdfasdfasdf", 99999)),
687 0);
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100688 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100689 ASSERT_DB_GET_AUC(imsi0, -ENOKEY);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200690
691
692 comment("Set auth data, 2G and 3G");
693
694 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
695 mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "CededEffacedAceFacedBadFadedBeef")),
696 0);
697 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
698 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
699 "BeefedCafeFaceAcedAddedDecadeFee", false,
700 "DeafBeddedBabeAcceededFadedDecaf", 5)),
701 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200702 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100703 ASSERT_DB_GET_AUC(imsi0, N_VECTORS);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200704
705
706 comment("Set invalid auth data");
707
708 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
709 mk_aud_2g(99999, "f000000000000f00000000000f000000")),
710 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200711 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200712
713 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
Harald Welte829713a2023-05-30 16:57:27 +0200714 mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f000000000000f00000000000f000000f00000000")),
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200715 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200716 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200717
718 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
Harald Welte829713a2023-05-30 16:57:27 +0200719 mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")),
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200720 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200721 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200722
723 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
724 mk_aud_2g(OSMO_AUTH_ALG_MILENAGE, "0123456789abcdef0123456789abcdef")),
725 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200726 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200727
728 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
729 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
730 "0f000000000000f00000000000f000000", false,
731 "f000000000000f00000000000f000000", 5)),
732 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200733 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200734
735 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
736 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
737 "f000000000000f00000000000f000000", false,
738 "000000000000f00000000000f000000", 5)),
739 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200740 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200741
742 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
743 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
744 "f000000000000f00000000000f000000", false,
745 "f000000000000f00000000000f000000",
746 OSMO_MILENAGE_IND_BITLEN_MAX + 1)),
747 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200748 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200749
750 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
751 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
752 "X000000000000f00000000000f000000", false,
753 "f000000000000f00000000000f000000", 5)),
754 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200755 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200756
757 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
758 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
759 "f000000000000f00000000000f000000", false,
760 "f000000000000 f00000000000 f000000", 5)),
761 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200762 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200763
764 comment("Delete subscriber");
765
766 ASSERT_SEL(imsi, imsi0, 0);
767 ASSERT_RC(db_subscr_delete_by_id(dbc, id), 0);
768 ASSERT_SEL(imsi, imsi0, -ENOENT);
769
770 comment("Re-add subscriber and verify auth data didn't come back");
771
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100772 ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200773 ASSERT_SEL(imsi, imsi0, 0);
774
775 /* For this test to work, we want to get the same subscriber ID back,
776 * and make sure there are no auth data leftovers for this ID. */
777 OSMO_ASSERT(id == g_subscr.id);
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100778 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100779 ASSERT_DB_GET_AUC(imsi0, -ENOKEY);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200780
781 ASSERT_RC(db_subscr_delete_by_id(dbc, id), 0);
782 ASSERT_SEL(imsi, imsi0, -ENOENT);
Neels Hofmeyr2dee60e2017-11-23 15:27:50 +0100783 ASSERT_DB_GET_AUC(imsi0, -ENOENT);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200784
785 comment_end();
786}
787
Oliver Smith6401b902019-07-24 11:32:45 +0200788/* Make each key too short in this test. Note that we can't set them longer than the allowed size without changing the
789 * table structure. */
Harald Welte7a476532022-11-03 11:38:41 +0100790static void test_subscr_aud_invalid_len(void)
Oliver Smith6401b902019-07-24 11:32:45 +0200791{
792 int64_t id;
793
794 comment_start();
795 comment("Create subscriber");
796 ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
797 ASSERT_SEL(imsi, imsi0, 0);
798 id = g_subscr.id;
799
800
801 /* Invalid Ki length */
802 comment("Set auth data, 2G only, with invalid Ki length");
803 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
804 mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "0123456789abcdef0123456789abcdef")),
805 0);
806 /* Use raw SQL to avoid length check in db_subscr_update_aud_by_id(). This changes all rows in the table, which
807 * is fine for this test (implicit WHERE 1). */
808 db_raw_sql(dbc, "UPDATE auc_2g SET ki = '0123456789abcdef0123456789abcde'");
809 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
810
811 comment("Remove 2G auth data");
812 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
813 mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)),
814 0);
815
816 /* Invalid K length */
817 comment("Set auth data, 3G only, with invalid K length");
818 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
819 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
820 "BeefedCafeFaceAcedAddedDecadeFee", true,
821 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
822 0);
823 db_raw_sql(dbc, "UPDATE auc_3g SET k = 'C01ffedC1cadaeAc1d1f1edAcac1aB0'");
824 ASSERT_SEL_AUD(imsi0, -EIO, id);
825
826 /* Invalid OP length */
827 comment("Set auth data, 3G only, with invalid OP length");
828 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
829 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
830 "BeefedCafeFaceAcedAddedDecadeFee", true,
831 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
832 0);
833 db_raw_sql(dbc, "UPDATE auc_3g SET op = 'BeefedCafeFaceAcedAddedDecadeFe'");
834 ASSERT_SEL_AUD(imsi0, -EIO, id);
835
836 /* Invalid OPC length */
837 comment("Set auth data, 3G only, with invalid OPC length");
838 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
839 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
840 "BeefedCafeFaceAcedAddedDecadeFee", false,
841 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
842 0);
843 db_raw_sql(dbc, "UPDATE auc_3g SET opc = 'BeefedCafeFaceAcedAddedDecadeFe'");
844 ASSERT_SEL_AUD(imsi0, -EIO, id);
845
846
847 comment("Delete subscriber");
848 ASSERT_RC(db_subscr_delete_by_id(dbc, id), 0);
849 comment_end();
850}
851
Harald Welte7a476532022-11-03 11:38:41 +0100852static void test_subscr_sqn(void)
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +0200853{
854 int64_t id;
855
856 comment_start();
857
858 comment("Set SQN for unknown subscriber");
859
860 ASSERT_RC(db_update_sqn(dbc, 99, 999), -ENOENT);
861 ASSERT_SEL(id, 99, -ENOENT);
862
863 ASSERT_RC(db_update_sqn(dbc, 9999, 99), -ENOENT);
864 ASSERT_SEL(id, 9999, -ENOENT);
865
866 comment("Create subscriber");
867
Oliver Smithcd2af5e2019-03-06 13:17:39 +0100868 ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +0200869 ASSERT_SEL(imsi, imsi0, 0);
870
871 id = g_subscr.id;
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100872 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +0200873
874 comment("Set SQN, but no 3G auth data present");
875
876 ASSERT_RC(db_update_sqn(dbc, id, 123), -ENOENT);
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100877 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +0200878
879 ASSERT_RC(db_update_sqn(dbc, id, 543), -ENOENT);
Neels Hofmeyrbd1dca02017-11-23 15:25:30 +0100880 ASSERT_SEL_AUD(imsi0, -ENOKEY, id);
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +0200881
882 comment("Set auth 3G data");
883
884 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
885 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
886 "BeefedCafeFaceAcedAddedDecadeFee", true,
887 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
888 0);
889 ASSERT_SEL_AUD(imsi0, 0, id);
890
891 comment("Set SQN");
892
893 ASSERT_RC(db_update_sqn(dbc, id, 23315), 0);
894 ASSERT_SEL_AUD(imsi0, 0, id);
895
896 ASSERT_RC(db_update_sqn(dbc, id, 23315), 0);
897 ASSERT_SEL_AUD(imsi0, 0, id);
898
899 ASSERT_RC(db_update_sqn(dbc, id, 423), 0);
900 ASSERT_SEL_AUD(imsi0, 0, id);
901
902 comment("Set SQN: thru uint64_t range, using the int64_t SQLite bind");
903
904 ASSERT_RC(db_update_sqn(dbc, id, 0), 0);
905 ASSERT_SEL_AUD(imsi0, 0, id);
906
907 ASSERT_RC(db_update_sqn(dbc, id, INT64_MAX), 0);
908 ASSERT_SEL_AUD(imsi0, 0, id);
909
910 ASSERT_RC(db_update_sqn(dbc, id, INT64_MIN), 0);
911 ASSERT_SEL_AUD(imsi0, 0, id);
912
913 ASSERT_RC(db_update_sqn(dbc, id, UINT64_MAX), 0);
914 ASSERT_SEL_AUD(imsi0, 0, id);
915
916 comment("Delete subscriber");
917
918 ASSERT_SEL(imsi, imsi0, 0);
919 ASSERT_RC(db_subscr_delete_by_id(dbc, id), 0);
920 ASSERT_SEL(imsi, imsi0, -ENOENT);
921
922 comment_end();
923}
924
Harald Welte7a476532022-11-03 11:38:41 +0100925static void test_ind(void)
Neels Hofmeyr3f9d1972019-12-12 04:04:53 +0100926{
927 comment_start();
928
929#define ASSERT_IND(VLR, IND) do { \
930 unsigned int ind; \
931 struct osmo_cni_peer_id vlr; \
932 OSMO_ASSERT(!osmo_cni_peer_id_set_str(&vlr, OSMO_CNI_PEER_ID_IPA_NAME, VLR)); \
933 ASSERT_RC(db_ind(dbc, &vlr, &ind), 0); \
934 fprintf(stderr, "%s ind = %u\n\n", osmo_quote_str((char*)vlr.ipa_name.val, vlr.ipa_name.len), ind); \
935 if (ind != (IND)) \
936 fprintf(stderr, " ERROR: expected " #IND "\n"); \
937 } while (0)
938#define IND_DEL(VLR) do { \
939 struct osmo_cni_peer_id vlr; \
940 OSMO_ASSERT(!osmo_cni_peer_id_set_str(&vlr, OSMO_CNI_PEER_ID_IPA_NAME, VLR)); \
941 ASSERT_RC(db_ind_del(dbc, &vlr), 0); \
942 fprintf(stderr, "%s ind deleted\n\n", osmo_quote_str((char*)vlr.ipa_name.val, vlr.ipa_name.len)); \
943 } while (0)
944
945 ASSERT_IND("msc-23", 1);
946 ASSERT_IND("sgsn-11", 2);
947 ASSERT_IND("msc-42", 3);
948 ASSERT_IND("sgsn-22", 4);
949 ASSERT_IND("msc-0x17", 5);
950 ASSERT_IND("sgsn-0xaa", 6);
951 ASSERT_IND("msc-42", 3);
952 ASSERT_IND("sgsn-22", 4);
953 ASSERT_IND("msc-0x17", 5);
954 ASSERT_IND("sgsn-0xaa", 6);
955 ASSERT_IND("sgsn-0xbb", 7);
956 ASSERT_IND("msc-0x2a", 8);
957 ASSERT_IND("msc-42", 3);
958 ASSERT_IND("sgsn-22", 4);
959 ASSERT_IND("msc-23", 1);
960 ASSERT_IND("sgsn-11", 2);
961
962 IND_DEL("msc-0x17"); /* dropped IND == 5 */
963 ASSERT_IND("msc-0x2a", 8); /* known CS remains where it is */
964 ASSERT_IND("any-unknown", 9); /* new VLR takes a new IND from the end */
965
966 comment_end();
967}
968
Neels Hofmeyr98509462017-10-09 17:28:53 +0200969static struct {
970 bool verbose;
971} cmdline_opts = {
972 .verbose = false,
973};
974
975static void print_help(const char *program)
976{
977 printf("Usage:\n"
978 " %s [-v] [N [N...]]\n"
979 "Options:\n"
980 " -h --help show this text.\n"
981 " -v --verbose print source file and line numbers\n",
982 program
983 );
984}
985
986static void handle_options(int argc, char **argv)
987{
988 while (1) {
989 int option_index = 0, c;
990 static struct option long_options[] = {
991 {"help", 0, 0, 'h'},
992 {"verbose", 1, 0, 'v'},
993 {0, 0, 0, 0}
994 };
995
996 c = getopt_long(argc, argv, "hv",
997 long_options, &option_index);
998 if (c == -1)
999 break;
1000
1001 switch (c) {
1002 case 'h':
1003 print_help(argv[0]);
1004 exit(0);
1005 case 'v':
1006 cmdline_opts.verbose = true;
1007 break;
1008 default:
1009 /* catch unknown options *as well as* missing arguments. */
1010 fprintf(stderr, "Error in command line options. Exiting.\n");
1011 exit(-1);
1012 break;
1013 }
1014 }
1015
1016 if (optind < argc) {
1017 fprintf(stderr, "too many args\n");
1018 exit(-1);
1019 }
1020}
1021
1022int main(int argc, char **argv)
1023{
1024 printf("db_test.c\n");
1025
1026 ctx = talloc_named_const(NULL, 1, "db_test");
1027
1028 handle_options(argc, argv);
1029
Pau Espin Pedrol51530312018-04-17 15:07:06 +02001030 osmo_init_logging2(ctx, &hlr_log_info);
Pau Espin Pedrold6993ea2021-02-19 13:20:18 +01001031 log_set_print_filename2(osmo_stderr_target,
1032 cmdline_opts.verbose ?
1033 LOG_FILENAME_BASENAME :
1034 LOG_FILENAME_NONE);
Neels Hofmeyr98509462017-10-09 17:28:53 +02001035 log_set_print_timestamp(osmo_stderr_target, 0);
1036 log_set_use_color(osmo_stderr_target, 0);
Pau Espin Pedrold6993ea2021-02-19 13:20:18 +01001037 log_set_print_category_hex(osmo_stderr_target, 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +02001038 log_set_print_category(osmo_stderr_target, 1);
Neels Hofmeyr6eb231e2017-10-27 03:35:45 +02001039 log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
Neels Hofmeyr98509462017-10-09 17:28:53 +02001040
1041 /* omit the SQLite version and compilation flags from test output */
1042 log_set_log_level(osmo_stderr_target, LOGL_ERROR);
Neels Hofmeyrd3814b92017-11-21 12:28:07 +01001043 /* Disable SQLite logging so that we're not vulnerable on SQLite error messages changing across
1044 * library versions. */
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +01001045 dbc = db_open(ctx, "db_test.db", false, false);
Neels Hofmeyr98509462017-10-09 17:28:53 +02001046 log_set_log_level(osmo_stderr_target, 0);
1047 OSMO_ASSERT(dbc);
1048
1049 test_subscr_create_update_sel_delete();
Neels Hofmeyr1332a172017-10-10 02:25:00 +02001050 test_subscr_aud();
Oliver Smith6401b902019-07-24 11:32:45 +02001051 test_subscr_aud_invalid_len();
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +02001052 test_subscr_sqn();
Neels Hofmeyr3f9d1972019-12-12 04:04:53 +01001053 test_ind();
Neels Hofmeyr98509462017-10-09 17:28:53 +02001054
1055 printf("Done\n");
Vadim Yanitskiydc301542019-07-26 18:38:49 +07001056 db_close(dbc);
Neels Hofmeyr98509462017-10-09 17:28:53 +02001057 return 0;
1058}
1059
1060/* stubs */
Neels Hofmeyr00b1d432017-10-17 01:43:48 +02001061void *lu_op_alloc_conn(void *conn)
1062{ OSMO_ASSERT(false); return NULL; }
1063void lu_op_tx_del_subscr_data(void *luop)
1064{ OSMO_ASSERT(false); }
1065void lu_op_free(void *luop)
1066{ OSMO_ASSERT(false); }