blob: 23b84cc8a922d3bd406dd6cb894ebf7b69ba2d31 [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
30#include "db.h"
31#include "logging.h"
32
33#define comment_start() fprintf(stderr, "\n===== %s\n", __func__);
34#define comment(fmt, args...) fprintf(stderr, "\n--- " fmt "\n\n", ## args);
35#define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__);
36
Neels Hofmeyrb6837e32017-10-10 23:20:26 +020037#define fill_invalid(x) _fill_invalid(&x, sizeof(x))
38static void _fill_invalid(void *dest, size_t size)
39{
40 uint8_t *pos = dest;
41 size_t remain = size;
42 int wrote = 0;
43 do {
44 remain -= wrote;
45 pos += wrote;
46 wrote = snprintf((void*)pos, remain, "-invalid-data");
47 } while (wrote < remain);
48}
49
Neels Hofmeyr98509462017-10-09 17:28:53 +020050/* Perform a function call and verbosely assert that its return value is as expected.
51 * The return code is then available in g_rc. */
52#define ASSERT_RC(call, expect_rc) \
53 do { \
54 fprintf(stderr, #call " --> " #expect_rc "\n"); \
55 g_rc = call; \
56 if (g_rc != (expect_rc)) \
57 fprintf(stderr, " MISMATCH: got rc = %d, expected: " \
58 #expect_rc " = %d\n", g_rc, expect_rc); \
59 OSMO_ASSERT(g_rc == (expect_rc)); \
60 fprintf(stderr, "\n"); \
61 } while (0)
62
63/* Do db_subscr_get_by_xxxx and verbosely assert that its return value is as expected.
64 * Print the subscriber struct to stderr to be validated by db_test.err.
65 * The result is then available in g_subscr. */
66#define ASSERT_SEL(by, val, expect_rc) \
67 do { \
68 int rc; \
Neels Hofmeyrb6837e32017-10-10 23:20:26 +020069 fill_invalid(g_subscr); \
Neels Hofmeyr98509462017-10-09 17:28:53 +020070 fprintf(stderr, "db_subscr_get_by_" #by "(dbc, " #val ", &g_subscr) --> " \
71 #expect_rc "\n"); \
72 rc = db_subscr_get_by_##by(dbc, val, &g_subscr); \
73 if (rc != (expect_rc)) \
74 fprintf(stderr, " MISMATCH: got rc = %d, expected: " \
75 #expect_rc " = %d\n", rc, expect_rc); \
76 OSMO_ASSERT(rc == (expect_rc)); \
77 if (!rc) \
78 dump_subscr(&g_subscr); \
79 fprintf(stderr, "\n"); \
80 } while (0)
81
Neels Hofmeyr1332a172017-10-10 02:25:00 +020082/* Do db_get_auth_data() and verbosely assert that its return value is as expected.
83 * Print the subscriber struct to stderr to be validated by db_test.err.
84 * The results are then available in g_aud2g and g_aud3g. */
85#define ASSERT_SEL_AUD(imsi, expect_rc, expect_id) \
86 do { \
Neels Hofmeyrb6837e32017-10-10 23:20:26 +020087 fill_invalid(g_aud2g); \
88 fill_invalid(g_aud3g); \
Neels Hofmeyr1332a172017-10-10 02:25:00 +020089 g_id = 0; \
90 ASSERT_RC(db_get_auth_data(dbc, imsi, &g_aud2g, &g_aud3g, &g_id), expect_rc); \
Neels Hofmeyr57a87922017-10-09 17:51:13 +020091 if (!g_rc) { \
Neels Hofmeyr1332a172017-10-10 02:25:00 +020092 dump_aud("2G", &g_aud2g); \
93 dump_aud("3G", &g_aud3g); \
94 }\
95 if (g_id != expect_id) {\
96 fprintf(stderr, "MISMATCH: got subscriber id %"PRId64 \
97 ", expected %"PRId64"\n", g_id, (int64_t)(expect_id)); \
98 OSMO_ASSERT(g_id == expect_id); \
99 } \
100 fprintf(stderr, "\n"); \
101 } while (0)
102
Neels Hofmeyr98509462017-10-09 17:28:53 +0200103static struct db_context *dbc = NULL;
104static void *ctx = NULL;
105static struct hlr_subscriber g_subscr;
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200106static struct osmo_sub_auth_data g_aud2g;
107static struct osmo_sub_auth_data g_aud3g;
Neels Hofmeyr98509462017-10-09 17:28:53 +0200108static int g_rc;
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200109static int64_t g_id;
Neels Hofmeyr98509462017-10-09 17:28:53 +0200110
111#define Pfv(name, fmt, val) \
112 fprintf(stderr, " ." #name " = " fmt ",\n", val)
113#define Pfo(name, fmt, obj) \
114 Pfv(name, fmt, obj->name)
115
116/* Print a subscriber struct to stderr to be validated by db_test.err. */
117void dump_subscr(struct hlr_subscriber *subscr)
118{
119#define Ps(name) \
120 if (*subscr->name) \
121 Pfo(name, "'%s'", subscr)
122#define Pd(name) \
123 Pfv(name, "%"PRId64, (int64_t)subscr->name)
124#define Pd_nonzero(name) \
125 if (subscr->name) \
126 Pd(name)
127#define Pb(if_val, name) \
128 if (subscr->name == (if_val)) \
129 Pfv(name, "%s", subscr->name ? "true" : "false")
130
131 fprintf(stderr, "struct hlr_subscriber {\n");
132 Pd(id);
133 Ps(imsi);
134 Ps(msisdn);
135 Ps(vlr_number);
136 Ps(sgsn_number);
137 Ps(sgsn_address);
138 Pd_nonzero(periodic_lu_timer);
139 Pd_nonzero(periodic_rau_tau_timer);
140 Pb(false, nam_cs);
141 Pb(false, nam_ps);
142 if (subscr->lmsi)
143 Pfo(lmsi, "0x%x", subscr);
144 Pb(true, ms_purged_cs);
145 Pb(true, ms_purged_ps);
146 fprintf(stderr, "}\n");
147#undef Ps
148#undef Pd
149#undef Pd_nonzero
150#undef Pb
151}
152
153void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
154{
155 if (aud->type == OSMO_AUTH_TYPE_NONE) {
156 fprintf(stderr, "%s: none\n", label);
157 return;
158 }
159
160 fprintf(stderr, "%s: struct osmo_sub_auth_data {\n", label);
161#define Pf(name, fmt) \
162 Pfo(name, fmt, aud)
163#define Phex(name) \
164 Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name)))
165
166 Pfv(type, "%s", osmo_sub_auth_type_name(aud->type));
167 Pfv(algo, "%s", osmo_auth_alg_name(aud->algo));
168 switch (aud->type) {
169 case OSMO_AUTH_TYPE_GSM:
170 Phex(u.gsm.ki);
171 break;
172 case OSMO_AUTH_TYPE_UMTS:
173 Phex(u.umts.opc);
174 Pf(u.umts.opc_is_op, "%u");
175 Phex(u.umts.k);
176 Phex(u.umts.amf);
177 if (aud->u.umts.sqn) {
178 Pf(u.umts.sqn, "%"PRIu64);
179 Pf(u.umts.sqn, "0x%"PRIx64);
180 }
181 if (aud->u.umts.ind_bitlen)
182 Pf(u.umts.ind_bitlen, "%u");
183 break;
184 default:
185 OSMO_ASSERT(false);
186 }
187
188 fprintf(stderr, "}\n");
189
190#undef Pf
191#undef Phex
192}
193
194static const char *imsi0 = "123456789000000";
195static const char *imsi1 = "123456789000001";
196static const char *imsi2 = "123456789000002";
197static const char *short_imsi = "123456";
198static const char *unknown_imsi = "999999999";
199
200static void test_subscr_create_update_sel_delete()
201{
202 int64_t id0, id1, id2, id_short;
203 comment_start();
204
205 comment("Create with valid / invalid IMSI");
206
207 ASSERT_RC(db_subscr_create(dbc, imsi0), 0);
208 ASSERT_SEL(imsi, imsi0, 0);
209 id0 = g_subscr.id;
210 ASSERT_RC(db_subscr_create(dbc, imsi1), 0);
211 ASSERT_SEL(imsi, imsi1, 0);
212 id1 = g_subscr.id;
213 ASSERT_RC(db_subscr_create(dbc, imsi2), 0);
214 ASSERT_SEL(imsi, imsi2, 0);
215 id2 = g_subscr.id;
216 ASSERT_RC(db_subscr_create(dbc, imsi0), -EIO);
217 ASSERT_SEL(imsi, imsi0, 0);
218 ASSERT_RC(db_subscr_create(dbc, imsi1), -EIO);
219 ASSERT_RC(db_subscr_create(dbc, imsi1), -EIO);
220 ASSERT_SEL(imsi, imsi1, 0);
221 ASSERT_RC(db_subscr_create(dbc, imsi2), -EIO);
222 ASSERT_RC(db_subscr_create(dbc, imsi2), -EIO);
223 ASSERT_SEL(imsi, imsi2, 0);
224
225 ASSERT_RC(db_subscr_create(dbc, "123456789 000003"), -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200226 ASSERT_SEL(imsi, "123456789000003", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200227
228 ASSERT_RC(db_subscr_create(dbc, "123456789000002123456"), -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200229 ASSERT_SEL(imsi, "123456789000002123456", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200230
231 ASSERT_RC(db_subscr_create(dbc, "foobar123"), -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200232 ASSERT_SEL(imsi, "foobar123", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200233
234 ASSERT_RC(db_subscr_create(dbc, "123"), -EINVAL);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200235 ASSERT_SEL(imsi, "123", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200236
237 ASSERT_RC(db_subscr_create(dbc, short_imsi), 0);
238 ASSERT_SEL(imsi, short_imsi, 0);
239 id_short = g_subscr.id;
240
241
242 comment("Set valid / invalid MSISDN");
243
244 ASSERT_SEL(imsi, imsi0, 0);
245 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0, "54321"), 0);
246 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200247 ASSERT_SEL(msisdn, "54321", 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200248 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
249 "54321012345678912345678"), -EINVAL);
250 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200251 ASSERT_SEL(msisdn, "54321", 0);
252 ASSERT_SEL(msisdn, "54321012345678912345678", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200253 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
254 "543 21"), -EINVAL);
255 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200256 ASSERT_SEL(msisdn, "543 21", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200257 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
258 "foobar123"), -EINVAL);
259 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200260 ASSERT_SEL(msisdn, "foobar123", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200261 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
262 "5"), 0);
263 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200264 ASSERT_SEL(msisdn, "5", 0);
265 ASSERT_SEL(msisdn, "54321", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200266 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
267 "543210123456789"), 0);
268 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200269 ASSERT_SEL(msisdn, "543210123456789", 0);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200270 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, imsi0,
271 "5432101234567891"), -EINVAL);
272 ASSERT_SEL(imsi, imsi0, 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200273 ASSERT_SEL(msisdn, "5432101234567891", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200274
275 comment("Set MSISDN on non-existent / invalid IMSI");
276
277 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, unknown_imsi, "99"), -ENOENT);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200278 ASSERT_SEL(msisdn, "99", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200279
280 ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, "foobar", "99"), -ENOENT);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200281 ASSERT_SEL(msisdn, "99", -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200282
Neels Hofmeyre8ccd502017-10-06 04:10:06 +0200283 comment("Set / unset nam_cs and nam_ps");
284
285 /* nam_val, is_ps */
286 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, true), 0);
287 ASSERT_SEL(imsi, imsi0, 0);
288 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, false), 0);
289 ASSERT_SEL(imsi, imsi0, 0);
290 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, false), 0);
291 ASSERT_SEL(imsi, imsi0, 0);
292 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, true), 0);
293 ASSERT_SEL(imsi, imsi0, 0);
294
295 comment("Set / unset nam_cs and nam_ps *again*");
296 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, true), 0);
297 ASSERT_SEL(imsi, imsi0, 0);
298 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, true), 0);
299 ASSERT_SEL(imsi, imsi0, 0);
300 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, false), 0);
301 ASSERT_SEL(imsi, imsi0, 0);
302 ASSERT_RC(db_subscr_nam(dbc, imsi0, false, false), 0);
303 ASSERT_SEL(imsi, imsi0, 0);
304 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, true), 0);
305 ASSERT_SEL(imsi, imsi0, 0);
306 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, true), 0);
307 ASSERT_SEL(imsi, imsi0, 0);
308 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, false), 0);
309 ASSERT_SEL(imsi, imsi0, 0);
310 ASSERT_RC(db_subscr_nam(dbc, imsi0, true, false), 0);
311 ASSERT_SEL(imsi, imsi0, 0);
312
313 comment("Set nam_cs and nam_ps on non-existent / invalid IMSI");
314
315 ASSERT_RC(db_subscr_nam(dbc, unknown_imsi, false, true), -ENOENT);
316 ASSERT_RC(db_subscr_nam(dbc, unknown_imsi, false, false), -ENOENT);
317 ASSERT_SEL(imsi, unknown_imsi, -ENOENT);
318
319 ASSERT_RC(db_subscr_nam(dbc, "foobar", false, true), -ENOENT);
320 ASSERT_RC(db_subscr_nam(dbc, "foobar", false, false), -ENOENT);
321
Neels Hofmeyrdd783052017-10-09 17:36:08 +0200322 comment("Record LU for PS and CS (SGSN and VLR names)");
323
324 ASSERT_RC(db_subscr_lu(dbc, id0, "5952", true), 0);
325 ASSERT_SEL(id, id0, 0);
326 ASSERT_RC(db_subscr_lu(dbc, id0, "712", false), 0);
327 ASSERT_SEL(id, id0, 0);
328
329 comment("Record LU for PS and CS (SGSN and VLR names) *again*");
330
331 ASSERT_RC(db_subscr_lu(dbc, id0, "111", true), 0);
332 ASSERT_SEL(id, id0, 0);
333 ASSERT_RC(db_subscr_lu(dbc, id0, "111", true), 0);
334 ASSERT_SEL(id, id0, 0);
335 ASSERT_RC(db_subscr_lu(dbc, id0, "222", false), 0);
336 ASSERT_SEL(id, id0, 0);
337 ASSERT_RC(db_subscr_lu(dbc, id0, "222", false), 0);
338 ASSERT_SEL(id, id0, 0);
339
340 comment("Unset LU info for PS and CS (SGSN and VLR names)");
341 ASSERT_RC(db_subscr_lu(dbc, id0, "", true), 0);
342 ASSERT_SEL(id, id0, 0);
343 ASSERT_RC(db_subscr_lu(dbc, id0, "", false), 0);
344 ASSERT_SEL(id, id0, 0);
345
346 ASSERT_RC(db_subscr_lu(dbc, id0, "111", true), 0);
347 ASSERT_RC(db_subscr_lu(dbc, id0, "222", false), 0);
348 ASSERT_SEL(id, id0, 0);
349 ASSERT_RC(db_subscr_lu(dbc, id0, NULL, true), 0);
350 ASSERT_SEL(id, id0, 0);
351 ASSERT_RC(db_subscr_lu(dbc, id0, NULL, false), 0);
352 ASSERT_SEL(id, id0, 0);
353
354 comment("Record LU for non-existent ID");
355 ASSERT_RC(db_subscr_lu(dbc, 99999, "5952", true), -ENOENT);
356 ASSERT_RC(db_subscr_lu(dbc, 99999, "712", false), -ENOENT);
357 ASSERT_SEL(id, 99999, -ENOENT);
358
Neels Hofmeyre50121e2017-10-09 17:48:51 +0200359 comment("Purge and un-purge PS and CS");
360
361 /* purge_val, is_ps */
362 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, true), 0);
363 ASSERT_SEL(imsi, imsi0, 0);
364 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, false), 0);
365 ASSERT_SEL(imsi, imsi0, 0);
366 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, false), 0);
367 ASSERT_SEL(imsi, imsi0, 0);
368 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, true), 0);
369 ASSERT_SEL(imsi, imsi0, 0);
370
371 comment("Purge PS and CS *again*");
372
373 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, true), 0);
374 ASSERT_SEL(imsi, imsi0, 0);
375 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, true), 0);
376 ASSERT_SEL(imsi, imsi0, 0);
377 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, true), 0);
378 ASSERT_SEL(imsi, imsi0, 0);
379 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, true), 0);
380 ASSERT_SEL(imsi, imsi0, 0);
381 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, false), 0);
382 ASSERT_SEL(imsi, imsi0, 0);
383 ASSERT_RC(db_subscr_purge(dbc, imsi0, true, false), 0);
384 ASSERT_SEL(imsi, imsi0, 0);
385 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, false), 0);
386 ASSERT_SEL(imsi, imsi0, 0);
387 ASSERT_RC(db_subscr_purge(dbc, imsi0, false, false), 0);
388 ASSERT_SEL(imsi, imsi0, 0);
389
390 comment("Purge on non-existent / invalid IMSI");
391
392 ASSERT_RC(db_subscr_purge(dbc, unknown_imsi, true, true), -ENOENT);
393 ASSERT_SEL(imsi, unknown_imsi, -ENOENT);
394 ASSERT_RC(db_subscr_purge(dbc, unknown_imsi, true, false), -ENOENT);
395 ASSERT_SEL(imsi, unknown_imsi, -ENOENT);
396
Neels Hofmeyr98509462017-10-09 17:28:53 +0200397 comment("Delete non-existent / invalid IDs");
398
399 ASSERT_RC(db_subscr_delete_by_id(dbc, 999), -ENOENT);
400 ASSERT_RC(db_subscr_delete_by_id(dbc, -10), -ENOENT);
401
402 comment("Delete subscribers");
403
404 ASSERT_SEL(imsi, imsi0, 0);
405 ASSERT_RC(db_subscr_delete_by_id(dbc, id0), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200406 ASSERT_SEL(imsi, imsi0, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200407 ASSERT_RC(db_subscr_delete_by_id(dbc, id0), -ENOENT);
408
409 ASSERT_SEL(imsi, imsi1, 0);
410 ASSERT_RC(db_subscr_delete_by_id(dbc, id1), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200411 ASSERT_SEL(imsi, imsi1, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200412
413 ASSERT_SEL(imsi, imsi2, 0);
414 ASSERT_RC(db_subscr_delete_by_id(dbc, id2), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200415 ASSERT_SEL(imsi, imsi2, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200416
417 ASSERT_SEL(imsi, short_imsi, 0);
418 ASSERT_RC(db_subscr_delete_by_id(dbc, id_short), 0);
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +0200419 ASSERT_SEL(imsi, short_imsi, -ENOENT);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200420
421 comment_end();
422}
423
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200424static const struct sub_auth_data_str *mk_aud_2g(enum osmo_auth_algo algo,
425 const char *ki)
426{
427 static struct sub_auth_data_str aud;
428 aud = (struct sub_auth_data_str){
429 .type = OSMO_AUTH_TYPE_GSM,
430 .algo = algo,
431 .u.gsm.ki = ki,
432 };
433 return &aud;
434}
435
436static const struct sub_auth_data_str *mk_aud_3g(enum osmo_auth_algo algo,
437 const char *opc, bool opc_is_op,
438 const char *k, unsigned int ind_bitlen)
439{
440 static struct sub_auth_data_str aud;
441 aud = (struct sub_auth_data_str){
442 .type = OSMO_AUTH_TYPE_UMTS,
443 .algo = algo,
444 .u.umts.k = k,
445 .u.umts.opc = opc,
446 .u.umts.opc_is_op = opc_is_op ? 1 : 0,
447 .u.umts.ind_bitlen = ind_bitlen,
448 };
449 return &aud;
450}
451
452static void test_subscr_aud()
453{
454 int64_t id;
455
456 comment_start();
457
458 comment("Get auth data for non-existent subscriber");
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200459 ASSERT_SEL_AUD(unknown_imsi, -ENOENT, 0);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200460
461 comment("Create subscriber");
462
463 ASSERT_RC(db_subscr_create(dbc, imsi0), 0);
464 ASSERT_SEL(imsi, imsi0, 0);
465
466 id = g_subscr.id;
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200467 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200468
469
470 comment("Set auth data, 2G only");
471
472 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
473 mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "0123456789abcdef0123456789abcdef")),
474 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200475 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200476
477 /* same again */
478 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
479 mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "0123456789abcdef0123456789abcdef")),
480 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200481 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200482
483 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
484 mk_aud_2g(OSMO_AUTH_ALG_COMP128v2, "BeadedBeeAced1EbbedDefacedFacade")),
485 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200486 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200487
488 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
489 mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "DeafBeddedBabeAcceededFadedDecaf")),
490 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200491 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200492
493 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
494 mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
495 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200496 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200497
498 comment("Remove 2G auth data");
499
500 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
501 mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)),
502 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200503 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200504
505 /* Removing nothing results in -ENOENT */
506 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
507 mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)),
508 -ENOENT);
509
510 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
511 mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
512 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200513 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200514
515 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
516 mk_aud_2g(OSMO_AUTH_ALG_NONE, "f000000000000f00000000000f000000")),
517 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200518 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200519
520
521 comment("Set auth data, 3G only");
522
523 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
524 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
525 "BeefedCafeFaceAcedAddedDecadeFee", true,
526 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
527 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200528 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200529
530 /* same again */
531 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
532 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
533 "BeefedCafeFaceAcedAddedDecadeFee", true,
534 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
535 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200536 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200537
538 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
539 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
540 "Deaf0ff1ceD0d0DabbedD1ced1ceF00d", true,
541 "F1bbed0afD0eF0bD0ffed0ddF1fe0b0e", 0)),
542 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200543 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200544
545 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
546 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
547 "BeefedCafeFaceAcedAddedDecadeFee", false,
548 "DeafBeddedBabeAcceededFadedDecaf",
549 OSMO_MILENAGE_IND_BITLEN_MAX)),
550 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200551 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200552
553 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
554 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
555 "CededEffacedAceFacedBadFadedBeef", false,
556 "BeefedCafeFaceAcedAddedDecadeFee", 5)),
557 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200558 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200559
560 comment("Remove 3G auth data");
561
562 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
563 mk_aud_3g(OSMO_AUTH_ALG_NONE, NULL, false, NULL, 0)),
564 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200565 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200566
567 /* Removing nothing results in -ENOENT */
568 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
569 mk_aud_3g(OSMO_AUTH_ALG_NONE, NULL, false, NULL, 0)),
570 -ENOENT);
571
572 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
573 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
574 "CededEffacedAceFacedBadFadedBeef", false,
575 "BeefedCafeFaceAcedAddedDecadeFee", 5)),
576 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200577 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200578
579 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
580 mk_aud_3g(OSMO_AUTH_ALG_NONE,
581 "asdfasdfasd", false,
582 "asdfasdfasdf", 99999)),
583 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200584 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200585
586
587 comment("Set auth data, 2G and 3G");
588
589 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
590 mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "CededEffacedAceFacedBadFadedBeef")),
591 0);
592 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
593 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
594 "BeefedCafeFaceAcedAddedDecadeFee", false,
595 "DeafBeddedBabeAcceededFadedDecaf", 5)),
596 0);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200597 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200598
599
600 comment("Set invalid auth data");
601
602 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
603 mk_aud_2g(99999, "f000000000000f00000000000f000000")),
604 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200605 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200606
607 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
608 mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")),
609 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200610 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200611
612 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
613 mk_aud_2g(OSMO_AUTH_ALG_XOR, "f00")),
614 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200615 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200616
617 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
618 mk_aud_2g(OSMO_AUTH_ALG_MILENAGE, "0123456789abcdef0123456789abcdef")),
619 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200620 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200621
622 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
623 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
624 "0f000000000000f00000000000f000000", false,
625 "f000000000000f00000000000f000000", 5)),
626 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200627 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200628
629 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
630 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
631 "f000000000000f00000000000f000000", false,
632 "000000000000f00000000000f000000", 5)),
633 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200634 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200635
636 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
637 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
638 "f000000000000f00000000000f000000", false,
639 "f000000000000f00000000000f000000",
640 OSMO_MILENAGE_IND_BITLEN_MAX + 1)),
641 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200642 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200643
644 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
645 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
646 "X000000000000f00000000000f000000", false,
647 "f000000000000f00000000000f000000", 5)),
648 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200649 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200650
651 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
652 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
653 "f000000000000f00000000000f000000", false,
654 "f000000000000 f00000000000 f000000", 5)),
655 -EINVAL);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200656 ASSERT_SEL_AUD(imsi0, 0, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200657
658 comment("Delete subscriber");
659
660 ASSERT_SEL(imsi, imsi0, 0);
661 ASSERT_RC(db_subscr_delete_by_id(dbc, id), 0);
662 ASSERT_SEL(imsi, imsi0, -ENOENT);
663
664 comment("Re-add subscriber and verify auth data didn't come back");
665
666 ASSERT_RC(db_subscr_create(dbc, imsi0), 0);
667 ASSERT_SEL(imsi, imsi0, 0);
668
669 /* For this test to work, we want to get the same subscriber ID back,
670 * and make sure there are no auth data leftovers for this ID. */
671 OSMO_ASSERT(id == g_subscr.id);
Neels Hofmeyr57a87922017-10-09 17:51:13 +0200672 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200673
674 ASSERT_RC(db_subscr_delete_by_id(dbc, id), 0);
675 ASSERT_SEL(imsi, imsi0, -ENOENT);
676
677 comment_end();
678}
679
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +0200680static void test_subscr_sqn()
681{
682 int64_t id;
683
684 comment_start();
685
686 comment("Set SQN for unknown subscriber");
687
688 ASSERT_RC(db_update_sqn(dbc, 99, 999), -ENOENT);
689 ASSERT_SEL(id, 99, -ENOENT);
690
691 ASSERT_RC(db_update_sqn(dbc, 9999, 99), -ENOENT);
692 ASSERT_SEL(id, 9999, -ENOENT);
693
694 comment("Create subscriber");
695
696 ASSERT_RC(db_subscr_create(dbc, imsi0), 0);
697 ASSERT_SEL(imsi, imsi0, 0);
698
699 id = g_subscr.id;
700 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
701
702 comment("Set SQN, but no 3G auth data present");
703
704 ASSERT_RC(db_update_sqn(dbc, id, 123), -ENOENT);
705 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
706
707 ASSERT_RC(db_update_sqn(dbc, id, 543), -ENOENT);
708 ASSERT_SEL_AUD(imsi0, -ENOENT, id);
709
710 comment("Set auth 3G data");
711
712 ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
713 mk_aud_3g(OSMO_AUTH_ALG_MILENAGE,
714 "BeefedCafeFaceAcedAddedDecadeFee", true,
715 "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 5)),
716 0);
717 ASSERT_SEL_AUD(imsi0, 0, id);
718
719 comment("Set SQN");
720
721 ASSERT_RC(db_update_sqn(dbc, id, 23315), 0);
722 ASSERT_SEL_AUD(imsi0, 0, id);
723
724 ASSERT_RC(db_update_sqn(dbc, id, 23315), 0);
725 ASSERT_SEL_AUD(imsi0, 0, id);
726
727 ASSERT_RC(db_update_sqn(dbc, id, 423), 0);
728 ASSERT_SEL_AUD(imsi0, 0, id);
729
730 comment("Set SQN: thru uint64_t range, using the int64_t SQLite bind");
731
732 ASSERT_RC(db_update_sqn(dbc, id, 0), 0);
733 ASSERT_SEL_AUD(imsi0, 0, id);
734
735 ASSERT_RC(db_update_sqn(dbc, id, INT64_MAX), 0);
736 ASSERT_SEL_AUD(imsi0, 0, id);
737
738 ASSERT_RC(db_update_sqn(dbc, id, INT64_MIN), 0);
739 ASSERT_SEL_AUD(imsi0, 0, id);
740
741 ASSERT_RC(db_update_sqn(dbc, id, UINT64_MAX), 0);
742 ASSERT_SEL_AUD(imsi0, 0, id);
743
744 comment("Delete subscriber");
745
746 ASSERT_SEL(imsi, imsi0, 0);
747 ASSERT_RC(db_subscr_delete_by_id(dbc, id), 0);
748 ASSERT_SEL(imsi, imsi0, -ENOENT);
749
750 comment_end();
751}
752
Neels Hofmeyr98509462017-10-09 17:28:53 +0200753static struct {
754 bool verbose;
755} cmdline_opts = {
756 .verbose = false,
757};
758
759static void print_help(const char *program)
760{
761 printf("Usage:\n"
762 " %s [-v] [N [N...]]\n"
763 "Options:\n"
764 " -h --help show this text.\n"
765 " -v --verbose print source file and line numbers\n",
766 program
767 );
768}
769
770static void handle_options(int argc, char **argv)
771{
772 while (1) {
773 int option_index = 0, c;
774 static struct option long_options[] = {
775 {"help", 0, 0, 'h'},
776 {"verbose", 1, 0, 'v'},
777 {0, 0, 0, 0}
778 };
779
780 c = getopt_long(argc, argv, "hv",
781 long_options, &option_index);
782 if (c == -1)
783 break;
784
785 switch (c) {
786 case 'h':
787 print_help(argv[0]);
788 exit(0);
789 case 'v':
790 cmdline_opts.verbose = true;
791 break;
792 default:
793 /* catch unknown options *as well as* missing arguments. */
794 fprintf(stderr, "Error in command line options. Exiting.\n");
795 exit(-1);
796 break;
797 }
798 }
799
800 if (optind < argc) {
801 fprintf(stderr, "too many args\n");
802 exit(-1);
803 }
804}
805
806int main(int argc, char **argv)
807{
808 printf("db_test.c\n");
809
810 ctx = talloc_named_const(NULL, 1, "db_test");
811
812 handle_options(argc, argv);
813
814 osmo_init_logging(&hlr_log_info);
815 log_set_print_filename(osmo_stderr_target, cmdline_opts.verbose);
816 log_set_print_timestamp(osmo_stderr_target, 0);
817 log_set_use_color(osmo_stderr_target, 0);
818 log_set_print_category(osmo_stderr_target, 1);
Neels Hofmeyr6eb231e2017-10-27 03:35:45 +0200819 log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
Neels Hofmeyr98509462017-10-09 17:28:53 +0200820
821 /* omit the SQLite version and compilation flags from test output */
822 log_set_log_level(osmo_stderr_target, LOGL_ERROR);
Neels Hofmeyrd3814b92017-11-21 12:28:07 +0100823 /* Disable SQLite logging so that we're not vulnerable on SQLite error messages changing across
824 * library versions. */
825 dbc = db_open(ctx, "db_test.db", false);
Neels Hofmeyr98509462017-10-09 17:28:53 +0200826 log_set_log_level(osmo_stderr_target, 0);
827 OSMO_ASSERT(dbc);
828
829 test_subscr_create_update_sel_delete();
Neels Hofmeyr1332a172017-10-10 02:25:00 +0200830 test_subscr_aud();
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +0200831 test_subscr_sqn();
Neels Hofmeyr98509462017-10-09 17:28:53 +0200832
833 printf("Done\n");
834 return 0;
835}
836
837/* stubs */
838int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
839 struct osmo_sub_auth_data *aud2g,
840 struct osmo_sub_auth_data *aud3g,
841 const uint8_t *rand_auts, const uint8_t *auts)
842{ OSMO_ASSERT(false); return -1; }
Neels Hofmeyr00b1d432017-10-17 01:43:48 +0200843void *lu_op_alloc_conn(void *conn)
844{ OSMO_ASSERT(false); return NULL; }
845void lu_op_tx_del_subscr_data(void *luop)
846{ OSMO_ASSERT(false); }
847void lu_op_free(void *luop)
848{ OSMO_ASSERT(false); }