blob: 42e7b81ec04f078a0993fef44b45313fe7bd6e41 [file] [log] [blame]
Harald Welte3b6fb082016-04-25 18:46:22 +02001#include <string.h>
2
3#include <osmocom/core/logging.h>
4#include <osmocom/core/utils.h>
5#include <osmocom/core/application.h>
6#include <osmocom/gsm/gsup.h>
7
8#define VERBOSE_FPRINTF(...)
9
10/* Tests for osmo_gsup_messages.c */
11
12#define TEST_IMSI_IE 0x01, 0x08, 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
13#define TEST_IMSI_STR "123456789012345"
14
15static void test_gsup_messages_dec_enc(void)
16{
17 int test_idx;
18 int rc;
19 uint8_t buf[1024];
20
21 static const uint8_t send_auth_info_req[] = {
22 0x08,
23 TEST_IMSI_IE
24 };
25
26 static const uint8_t send_auth_info_err[] = {
27 0x09,
28 TEST_IMSI_IE,
29 0x02, 0x01, 0x07 /* GPRS no allowed */
30 };
31
32 static const uint8_t send_auth_info_res[] = {
33 0x0a,
34 TEST_IMSI_IE,
35 0x03, 0x22, /* Auth tuple */
36 0x20, 0x10,
37 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
38 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
39 0x21, 0x04,
40 0x21, 0x22, 0x23, 0x24,
41 0x22, 0x08,
42 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
43 0x03, 0x22, /* Auth tuple */
44 0x20, 0x10,
45 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
46 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
47 0x21, 0x04,
48 0xa1, 0xa2, 0xa3, 0xa4,
49 0x22, 0x08,
50 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
51 };
52
53 static const uint8_t update_location_req[] = {
54 0x04,
55 TEST_IMSI_IE,
56 };
57
58 static const uint8_t update_location_err[] = {
59 0x05,
60 TEST_IMSI_IE,
61 0x02, 0x01, 0x07 /* GPRS no allowed */
62 };
63
64 static const uint8_t update_location_res[] = {
65 0x06,
66 TEST_IMSI_IE,
67 0x08, 0x07, /* MSISDN of the subscriber */
68 0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43,
69 0x09, 0x07, /* HLR-Number of the subscriber */
70 0x91, 0x83, 0x52, 0x38, 0x48, 0x83, 0x93,
71 0x04, 0x00, /* PDP info complete */
72 0x05, 0x15,
73 0x10, 0x01, 0x01,
74 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
75 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
76 0x13, 0x01, 0x02,
77 0x05, 0x11,
78 0x10, 0x01, 0x02,
79 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
80 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
81 };
82
83 static const uint8_t location_cancellation_req[] = {
84 0x1c,
85 TEST_IMSI_IE,
86 0x06, 0x01, 0x00,
87 };
88
89 static const uint8_t location_cancellation_err[] = {
90 0x1d,
91 TEST_IMSI_IE,
92 0x02, 0x01, 0x03 /* Illegal MS */
93 };
94
95 static const uint8_t location_cancellation_res[] = {
96 0x1e,
97 TEST_IMSI_IE,
98 };
99
100 static const uint8_t purge_ms_req[] = {
101 0x0c,
102 TEST_IMSI_IE,
103 };
104
105 static const uint8_t purge_ms_err[] = {
106 0x0d,
107 TEST_IMSI_IE,
108 0x02, 0x01, 0x03, /* Illegal MS */
109 };
110
111 static const uint8_t purge_ms_res[] = {
112 0x0e,
113 TEST_IMSI_IE,
114 0x07, 0x00,
115 };
116
Neels Hofmeyrabb23692017-02-21 15:53:20 +0100117 static const uint8_t send_auth_info_res_umts[] = {
118 0x0a,
119 TEST_IMSI_IE,
120 0x03, 0x62, /* Auth tuple */
121 0x20, 0x10, /* rand */
122 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
123 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
124 0x21, 0x04, /* sres */
125 0x21, 0x22, 0x23, 0x24,
126 0x22, 0x08, /* kc */
127 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
128 0x23, 0x10, /* IK (UMTS) */
129 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
130 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
131 0x24, 0x10, /* CK (UMTS) */
132 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
133 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
134 0x25, 0x10, /* AUTN (UMTS) */
135 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
136 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
137 0x25, 0x08, /* RES (UMTS) */
138 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
139 0x03, 0x22, /* Auth tuple */
140 0x20, 0x10, /* rand */
141 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
142 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0x10,
143 0x21, 0x04, /* sres */
144 0xb1, 0xb2, 0xb3, 0xb4,
145 0x22, 0x08, /* kc */
146 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
147 0x23, 0x10, /* IK (UMTS) */
148 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
149 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xd0,
150 0x24, 0x10, /* CK (UMTS) */
151 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
152 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xe0,
153 0x25, 0x10, /* AUTN (UMTS) */
154 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
155 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xf0,
156 0x25, 0x08, /* RES (UMTS) */
157 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
158 };
159
160 static const uint8_t send_auth_info_req_auts[] = {
161 0x08,
162 TEST_IMSI_IE,
163 0x26, 0x0e,
164 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
165 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
166 0x20, 0x10,
167 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
168 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
169 };
170
Harald Welte3b6fb082016-04-25 18:46:22 +0200171 static const struct test {
172 char *name;
173 const uint8_t *data;
174 size_t data_len;
175 } test_messages[] = {
176 {"Send Authentication Info Request",
177 send_auth_info_req, sizeof(send_auth_info_req)},
178 {"Send Authentication Info Error",
179 send_auth_info_err, sizeof(send_auth_info_err)},
180 {"Send Authentication Info Result",
181 send_auth_info_res, sizeof(send_auth_info_res)},
182 {"Update Location Request",
183 update_location_req, sizeof(update_location_req)},
184 {"Update Location Error",
185 update_location_err, sizeof(update_location_err)},
186 {"Update Location Result",
187 update_location_res, sizeof(update_location_res)},
188 {"Location Cancellation Request",
189 location_cancellation_req, sizeof(location_cancellation_req)},
190 {"Location Cancellation Error",
191 location_cancellation_err, sizeof(location_cancellation_err)},
192 {"Location Cancellation Result",
193 location_cancellation_res, sizeof(location_cancellation_res)},
194 {"Purge MS Request",
195 purge_ms_req, sizeof(purge_ms_req)},
196 {"Purge MS Error",
197 purge_ms_err, sizeof(purge_ms_err)},
198 {"Purge MS Result",
199 purge_ms_res, sizeof(purge_ms_res)},
Neels Hofmeyrabb23692017-02-21 15:53:20 +0100200 {"Send Authentication Info Result with IK, CK, AUTN and RES (UMTS)",
201 send_auth_info_req_auts, sizeof(send_auth_info_req_auts)},
202 {"Send Authentication Info Request with AUTS and RAND (UMTS)",
203 send_auth_info_req_auts, sizeof(send_auth_info_req_auts)},
Harald Welte3b6fb082016-04-25 18:46:22 +0200204 };
205
206 printf("Test GSUP message decoding/encoding\n");
207
208 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
209 const struct test *t = &test_messages[test_idx];
210 struct osmo_gsup_message gm = {0};
211 struct msgb *msg = msgb_alloc(4096, "gsup_test");
212
213 printf(" Testing %s\n", t->name);
214
215 rc = osmo_gsup_decode(t->data, t->data_len, &gm);
216 OSMO_ASSERT(rc >= 0);
217
218 osmo_gsup_encode(msg, &gm);
219
220 fprintf(stderr, " generated message: %s\n", msgb_hexdump(msg));
221 fprintf(stderr, " original message: %s\n", osmo_hexdump(t->data, t->data_len));
222 fprintf(stderr, " IMSI: %s\n", gm.imsi);
223 OSMO_ASSERT(strcmp(gm.imsi, TEST_IMSI_STR) == 0);
224 OSMO_ASSERT(msgb_length(msg) == t->data_len);
225 OSMO_ASSERT(memcmp(msgb_data(msg), t->data, t->data_len) == 0);
226
227 msgb_free(msg);
228 }
229
230 /* simple truncation test */
231 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
232 int j;
233 const struct test *t = &test_messages[test_idx];
234 int ie_end = t->data_len;
235 struct osmo_gsup_message gm = {0};
236 int counter = 0;
237 int parse_err = 0;
238
239 for (j = t->data_len - 1; j >= 0; --j) {
240 rc = osmo_gsup_decode(t->data, j, &gm);
241 counter += 1;
242
243 VERBOSE_FPRINTF(stderr,
244 " partial message decoding: "
245 "orig_len = %d, trunc = %d, rc = %d, ie_end = %d\n",
246 t->data_len, j, rc, ie_end);
247 if (rc >= 0) {
248 VERBOSE_FPRINTF(stderr,
249 " remaing partial message: %s\n",
250 osmo_hexdump(t->data + j, ie_end - j));
251
252 OSMO_ASSERT(j <= ie_end - 2);
Neels Hofmeyrabb23692017-02-21 15:53:20 +0100253 OSMO_ASSERT(t->data[j+0] <= OSMO_GSUP_CN_DOMAIN_IE);
Harald Welte3b6fb082016-04-25 18:46:22 +0200254 OSMO_ASSERT(t->data[j+1] <= ie_end - j - 2);
255
256 ie_end = j;
257 } else {
258 parse_err += 1;
259 }
260 }
261
262 fprintf(stderr,
263 " message %d: tested %d truncations, %d parse failures\n",
264 test_idx, counter, parse_err);
265 }
266
267 /* message modification test (relies on ASAN or valgrind being used) */
268 for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
269 int j;
270 const struct test *t = &test_messages[test_idx];
271 struct osmo_gsup_message gm = {0};
272 uint8_t val;
273 int counter = 0;
274 int parse_err = 0;
275
276 OSMO_ASSERT(sizeof(buf) >= t->data_len);
277
278 for (j = t->data_len - 1; j >= 0; --j) {
279 memcpy(buf, t->data, t->data_len);
280 val = 0;
281 do {
282 VERBOSE_FPRINTF(stderr,
283 "t = %d, len = %d, val = %d\n",
284 test_idx, j, val);
285 buf[j] = val;
286 rc = osmo_gsup_decode(buf, t->data_len, &gm);
287 counter += 1;
288 if (rc < 0)
289 parse_err += 1;
290
291 val += 1;
292 } while (val != (uint8_t)256);
293 }
294
295 fprintf(stderr,
296 " message %d: tested %d modifications, %d parse failures\n",
297 test_idx, counter, parse_err);
298 }
299}
300
301const struct log_info_cat default_categories[] = {
Harald Welte3b6fb082016-04-25 18:46:22 +0200302};
303
304static struct log_info info = {
305 .cat = default_categories,
306 .num_cat = ARRAY_SIZE(default_categories),
307};
308
309int main(int argc, char **argv)
310{
311 osmo_init_logging(&info);
312
313 test_gsup_messages_dec_enc();
314
315 printf("Done.\n");
316 return EXIT_SUCCESS;
317}