1 // SPDX-License-Identifier: GPL-2.0
2 /* Author: Dmitry Safonov <dima@arista.com> */
3 #include <inttypes.h>
4 #include "../../../../include/linux/kernel.h"
5 #include "aolib.h"
6
7 static union tcp_addr tcp_md5_client;
8
9 #define FILTER_TEST_NKEYS 16
10
11 static int test_port = 7788;
make_listen(int sk)12 static void make_listen(int sk)
13 {
14 sockaddr_af addr;
15
16 tcp_addr_to_sockaddr_in(&addr, &this_ip_addr, htons(test_port++));
17 if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0)
18 test_error("bind()");
19 if (listen(sk, 1))
20 test_error("listen()");
21 }
22
test_vefify_ao_info(int sk,struct tcp_ao_info_opt * info,const char * tst)23 static void test_vefify_ao_info(int sk, struct tcp_ao_info_opt *info,
24 const char *tst)
25 {
26 struct tcp_ao_info_opt tmp = {};
27 socklen_t len = sizeof(tmp);
28
29 if (getsockopt(sk, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
30 test_error("getsockopt(TCP_AO_INFO) failed");
31
32 #define __cmp_ao(member) \
33 do { \
34 if (info->member != tmp.member) { \
35 test_fail("%s: getsockopt(): " __stringify(member) " %" PRIu64 " != %" PRIu64, \
36 tst, (uint64_t)info->member, (uint64_t)tmp.member); \
37 return; \
38 } \
39 } while(0)
40 if (info->set_current)
41 __cmp_ao(current_key);
42 if (info->set_rnext)
43 __cmp_ao(rnext);
44 if (info->set_counters) {
45 __cmp_ao(pkt_good);
46 __cmp_ao(pkt_bad);
47 __cmp_ao(pkt_key_not_found);
48 __cmp_ao(pkt_ao_required);
49 __cmp_ao(pkt_dropped_icmp);
50 }
51 __cmp_ao(ao_required);
52 __cmp_ao(accept_icmps);
53
54 test_ok("AO info get: %s", tst);
55 #undef __cmp_ao
56 }
57
__setsockopt_checked(int sk,int optname,bool get,void * optval,socklen_t * len,int err,const char * tst,const char * tst2)58 static void __setsockopt_checked(int sk, int optname, bool get,
59 void *optval, socklen_t *len,
60 int err, const char *tst, const char *tst2)
61 {
62 int ret;
63
64 if (!tst)
65 tst = "";
66 if (!tst2)
67 tst2 = "";
68
69 errno = 0;
70 if (get)
71 ret = getsockopt(sk, IPPROTO_TCP, optname, optval, len);
72 else
73 ret = setsockopt(sk, IPPROTO_TCP, optname, optval, *len);
74 if (ret == -1) {
75 if (errno == err)
76 test_ok("%s%s", tst ?: "", tst2 ?: "");
77 else
78 test_fail("%s%s: %setsockopt() failed",
79 tst, tst2, get ? "g" : "s");
80 close(sk);
81 return;
82 }
83
84 if (err) {
85 test_fail("%s%s: %setsockopt() was expected to fail with %d",
86 tst, tst2, get ? "g" : "s", err);
87 } else {
88 test_ok("%s%s", tst ?: "", tst2 ?: "");
89 if (optname == TCP_AO_ADD_KEY) {
90 test_verify_socket_key(sk, optval);
91 } else if (optname == TCP_AO_INFO && !get) {
92 test_vefify_ao_info(sk, optval, tst2);
93 } else if (optname == TCP_AO_GET_KEYS) {
94 if (*len != sizeof(struct tcp_ao_getsockopt))
95 test_fail("%s%s: get keys returned wrong tcp_ao_getsockopt size",
96 tst, tst2);
97 }
98 }
99 close(sk);
100 }
101
setsockopt_checked(int sk,int optname,void * optval,int err,const char * tst)102 static void setsockopt_checked(int sk, int optname, void *optval,
103 int err, const char *tst)
104 {
105 const char *cmd = NULL;
106 socklen_t len;
107
108 switch (optname) {
109 case TCP_AO_ADD_KEY:
110 cmd = "key add: ";
111 len = sizeof(struct tcp_ao_add);
112 break;
113 case TCP_AO_DEL_KEY:
114 cmd = "key del: ";
115 len = sizeof(struct tcp_ao_del);
116 break;
117 case TCP_AO_INFO:
118 cmd = "AO info set: ";
119 len = sizeof(struct tcp_ao_info_opt);
120 break;
121 default:
122 break;
123 }
124
125 __setsockopt_checked(sk, optname, false, optval, &len, err, cmd, tst);
126 }
127
prepare_defs(int cmd,void * optval)128 static int prepare_defs(int cmd, void *optval)
129 {
130 int sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
131
132 if (sk < 0)
133 test_error("socket()");
134
135 switch (cmd) {
136 case TCP_AO_ADD_KEY: {
137 struct tcp_ao_add *add = optval;
138
139 if (test_prepare_def_key(add, DEFAULT_TEST_PASSWORD, 0, this_ip_dest,
140 -1, 0, 100, 100))
141 test_error("prepare default tcp_ao_add");
142 break;
143 }
144 case TCP_AO_DEL_KEY: {
145 struct tcp_ao_del *del = optval;
146
147 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest,
148 DEFAULT_TEST_PREFIX, 100, 100))
149 test_error("add default key");
150 memset(del, 0, sizeof(struct tcp_ao_del));
151 del->sndid = 100;
152 del->rcvid = 100;
153 del->prefix = DEFAULT_TEST_PREFIX;
154 tcp_addr_to_sockaddr_in(&del->addr, &this_ip_dest, 0);
155 break;
156 }
157 case TCP_AO_INFO: {
158 struct tcp_ao_info_opt *info = optval;
159
160 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest,
161 DEFAULT_TEST_PREFIX, 100, 100))
162 test_error("add default key");
163 memset(info, 0, sizeof(struct tcp_ao_info_opt));
164 break;
165 }
166 case TCP_AO_GET_KEYS: {
167 struct tcp_ao_getsockopt *get = optval;
168
169 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest,
170 DEFAULT_TEST_PREFIX, 100, 100))
171 test_error("add default key");
172 memset(get, 0, sizeof(struct tcp_ao_getsockopt));
173 get->nkeys = 1;
174 get->get_all = 1;
175 break;
176 }
177 default:
178 test_error("unknown cmd");
179 }
180
181 return sk;
182 }
183
test_extend(int cmd,bool get,const char * tst,socklen_t under_size)184 static void test_extend(int cmd, bool get, const char *tst, socklen_t under_size)
185 {
186 struct {
187 union {
188 struct tcp_ao_add add;
189 struct tcp_ao_del del;
190 struct tcp_ao_getsockopt get;
191 struct tcp_ao_info_opt info;
192 };
193 char *extend[100];
194 } tmp_opt;
195 socklen_t extended_size = sizeof(tmp_opt);
196 int sk;
197
198 memset(&tmp_opt, 0, sizeof(tmp_opt));
199 sk = prepare_defs(cmd, &tmp_opt);
200 __setsockopt_checked(sk, cmd, get, &tmp_opt, &under_size,
201 EINVAL, tst, ": minimum size");
202
203 memset(&tmp_opt, 0, sizeof(tmp_opt));
204 sk = prepare_defs(cmd, &tmp_opt);
205 __setsockopt_checked(sk, cmd, get, &tmp_opt, &extended_size,
206 0, tst, ": extended size");
207
208 memset(&tmp_opt, 0, sizeof(tmp_opt));
209 sk = prepare_defs(cmd, &tmp_opt);
210 __setsockopt_checked(sk, cmd, get, NULL, &extended_size,
211 EFAULT, tst, ": null optval");
212
213 if (get) {
214 memset(&tmp_opt, 0, sizeof(tmp_opt));
215 sk = prepare_defs(cmd, &tmp_opt);
216 __setsockopt_checked(sk, cmd, get, &tmp_opt, NULL,
217 EFAULT, tst, ": null optlen");
218 }
219 }
220
extend_tests(void)221 static void extend_tests(void)
222 {
223 test_extend(TCP_AO_ADD_KEY, false, "AO add",
224 offsetof(struct tcp_ao_add, key));
225 test_extend(TCP_AO_DEL_KEY, false, "AO del",
226 offsetof(struct tcp_ao_del, keyflags));
227 test_extend(TCP_AO_INFO, false, "AO set info",
228 offsetof(struct tcp_ao_info_opt, pkt_dropped_icmp));
229 test_extend(TCP_AO_INFO, true, "AO get info", -1);
230 test_extend(TCP_AO_GET_KEYS, true, "AO get keys", -1);
231 }
232
test_optmem_limit(void)233 static void test_optmem_limit(void)
234 {
235 size_t i, keys_limit, current_optmem = test_get_optmem();
236 struct tcp_ao_add ao;
237 union tcp_addr net = {};
238 int sk;
239
240 if (inet_pton(TEST_FAMILY, TEST_NETWORK, &net) != 1)
241 test_error("Can't convert ip address %s", TEST_NETWORK);
242
243 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
244 keys_limit = current_optmem / KERNEL_TCP_AO_KEY_SZ_ROUND_UP;
245 for (i = 0;; i++) {
246 union tcp_addr key_peer;
247 int err;
248
249 key_peer = gen_tcp_addr(net, i + 1);
250 tcp_addr_to_sockaddr_in(&ao.addr, &key_peer, 0);
251 err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY,
252 &ao, sizeof(ao));
253 if (!err) {
254 /*
255 * TCP_AO_ADD_KEY should be the same order as the real
256 * sizeof(struct tcp_ao_key) in kernel.
257 */
258 if (i <= keys_limit * 10)
259 continue;
260 test_fail("optmem limit test failed: added %zu key", i);
261 break;
262 }
263 if (i < keys_limit) {
264 test_fail("optmem limit test failed: couldn't add %zu key", i);
265 break;
266 }
267 test_ok("optmem limit was hit on adding %zu key", i);
268 break;
269 }
270 close(sk);
271 }
272
test_einval_add_key(void)273 static void test_einval_add_key(void)
274 {
275 struct tcp_ao_add ao;
276 int sk;
277
278 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
279 ao.keylen = TCP_AO_MAXKEYLEN + 1;
280 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "too big keylen");
281
282 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
283 ao.reserved = 1;
284 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "using reserved padding");
285
286 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
287 ao.reserved2 = 1;
288 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "using reserved2 padding");
289
290 /* tcp_ao_verify_ipv{4,6}() checks */
291 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
292 ao.addr.ss_family = AF_UNIX;
293 memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
294 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "wrong address family");
295
296 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
297 tcp_addr_to_sockaddr_in(&ao.addr, &this_ip_dest, 1234);
298 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "port (unsupported)");
299
300 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
301 ao.prefix = 0;
302 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "no prefix, addr");
303
304 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
305 ao.prefix = 0;
306 memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
307 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "no prefix, any addr");
308
309 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
310 ao.prefix = 32;
311 memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
312 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "prefix, any addr");
313
314 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
315 ao.prefix = 129;
316 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "too big prefix");
317
318 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
319 ao.prefix = 2;
320 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "too short prefix");
321
322 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
323 ao.keyflags = (uint8_t)(-1);
324 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "bad key flags");
325
326 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
327 make_listen(sk);
328 ao.set_current = 1;
329 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add current key on a listen socket");
330
331 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
332 make_listen(sk);
333 ao.set_rnext = 1;
334 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add rnext key on a listen socket");
335
336 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
337 make_listen(sk);
338 ao.set_current = 1;
339 ao.set_rnext = 1;
340 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add current+rnext key on a listen socket");
341
342 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
343 ao.set_current = 1;
344 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as current");
345
346 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
347 ao.set_rnext = 1;
348 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as rnext");
349
350 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
351 ao.set_current = 1;
352 ao.set_rnext = 1;
353 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as current+rnext");
354
355 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
356 ao.ifindex = 42;
357 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL,
358 "ifindex without TCP_AO_KEYF_IFNINDEX");
359
360 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
361 ao.keyflags |= TCP_AO_KEYF_IFINDEX;
362 ao.ifindex = 42;
363 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "non-existent VRF");
364 /*
365 * tcp_md5_do_lookup{,_any_l3index}() are checked in unsigned-md5
366 * see client_vrf_tests().
367 */
368
369 test_optmem_limit();
370
371 /* tcp_ao_parse_crypto() */
372 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
373 ao.maclen = 100;
374 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EMSGSIZE, "maclen bigger than TCP hdr");
375
376 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
377 strcpy(ao.alg_name, "imaginary hash algo");
378 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, ENOENT, "bad algo");
379 }
380
test_einval_del_key(void)381 static void test_einval_del_key(void)
382 {
383 struct tcp_ao_del del;
384 int sk;
385
386 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
387 del.reserved = 1;
388 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "using reserved padding");
389
390 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
391 del.reserved2 = 1;
392 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "using reserved2 padding");
393
394 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
395 make_listen(sk);
396 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
397 test_error("add key");
398 del.set_current = 1;
399 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set current key on a listen socket");
400
401 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
402 make_listen(sk);
403 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
404 test_error("add key");
405 del.set_rnext = 1;
406 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set rnext key on a listen socket");
407
408 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
409 make_listen(sk);
410 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
411 test_error("add key");
412 del.set_current = 1;
413 del.set_rnext = 1;
414 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set current+rnext key on a listen socket");
415
416 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
417 del.keyflags = (uint8_t)(-1);
418 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "bad key flags");
419
420 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
421 del.ifindex = 42;
422 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL,
423 "ifindex without TCP_AO_KEYF_IFNINDEX");
424
425 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
426 del.keyflags |= TCP_AO_KEYF_IFINDEX;
427 del.ifindex = 42;
428 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "non-existent VRF");
429
430 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
431 del.set_current = 1;
432 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set non-existing current key");
433
434 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
435 del.set_rnext = 1;
436 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set non-existing rnext key");
437
438 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
439 del.set_current = 1;
440 del.set_rnext = 1;
441 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set non-existing current+rnext key");
442
443 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
444 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
445 test_error("add key");
446 del.set_current = 1;
447 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "set current key");
448
449 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
450 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
451 test_error("add key");
452 del.set_rnext = 1;
453 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "set rnext key");
454
455 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
456 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
457 test_error("add key");
458 del.set_current = 1;
459 del.set_rnext = 1;
460 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "set current+rnext key");
461
462 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
463 del.set_current = 1;
464 del.current_key = 100;
465 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as current key to be removed");
466
467 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
468 del.set_rnext = 1;
469 del.rnext = 100;
470 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as rnext key to be removed");
471
472 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
473 del.set_current = 1;
474 del.current_key = 100;
475 del.set_rnext = 1;
476 del.rnext = 100;
477 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as current+rnext key to be removed");
478
479 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
480 del.del_async = 1;
481 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "async on non-listen");
482
483 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
484 del.sndid = 101;
485 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "non-existing sndid");
486
487 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
488 del.rcvid = 101;
489 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "non-existing rcvid");
490
491 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
492 tcp_addr_to_sockaddr_in(&del.addr, &this_ip_addr, 0);
493 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "incorrect addr");
494
495 sk = prepare_defs(TCP_AO_DEL_KEY, &del);
496 setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "correct key delete");
497 }
498
test_einval_ao_info(void)499 static void test_einval_ao_info(void)
500 {
501 struct tcp_ao_info_opt info;
502 int sk;
503
504 sk = prepare_defs(TCP_AO_INFO, &info);
505 make_listen(sk);
506 info.set_current = 1;
507 setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set current key on a listen socket");
508
509 sk = prepare_defs(TCP_AO_INFO, &info);
510 make_listen(sk);
511 info.set_rnext = 1;
512 setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set rnext key on a listen socket");
513
514 sk = prepare_defs(TCP_AO_INFO, &info);
515 make_listen(sk);
516 info.set_current = 1;
517 info.set_rnext = 1;
518 setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set current+rnext key on a listen socket");
519
520 sk = prepare_defs(TCP_AO_INFO, &info);
521 info.reserved = 1;
522 setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "using reserved padding");
523
524 sk = prepare_defs(TCP_AO_INFO, &info);
525 info.reserved2 = 1;
526 setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "using reserved2 padding");
527
528 sk = prepare_defs(TCP_AO_INFO, &info);
529 info.accept_icmps = 1;
530 setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "accept_icmps");
531
532 sk = prepare_defs(TCP_AO_INFO, &info);
533 info.ao_required = 1;
534 setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "ao required");
535
536 if (!should_skip_test("ao required with MD5 key", KCONFIG_TCP_MD5)) {
537 sk = prepare_defs(TCP_AO_INFO, &info);
538 info.ao_required = 1;
539 if (test_set_md5(sk, tcp_md5_client, TEST_PREFIX, -1,
540 "long long secret")) {
541 test_error("setsockopt(TCP_MD5SIG_EXT)");
542 close(sk);
543 } else {
544 setsockopt_checked(sk, TCP_AO_INFO, &info, EKEYREJECTED,
545 "ao required with MD5 key");
546 }
547 }
548
549 sk = prepare_defs(TCP_AO_INFO, &info);
550 info.set_current = 1;
551 setsockopt_checked(sk, TCP_AO_INFO, &info, ENOENT, "set non-existing current key");
552
553 sk = prepare_defs(TCP_AO_INFO, &info);
554 info.set_rnext = 1;
555 setsockopt_checked(sk, TCP_AO_INFO, &info, ENOENT, "set non-existing rnext key");
556
557 sk = prepare_defs(TCP_AO_INFO, &info);
558 info.set_current = 1;
559 info.set_rnext = 1;
560 setsockopt_checked(sk, TCP_AO_INFO, &info, ENOENT, "set non-existing current+rnext key");
561
562 sk = prepare_defs(TCP_AO_INFO, &info);
563 info.set_current = 1;
564 info.current_key = 100;
565 setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set current key");
566
567 sk = prepare_defs(TCP_AO_INFO, &info);
568 info.set_rnext = 1;
569 info.rnext = 100;
570 setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set rnext key");
571
572 sk = prepare_defs(TCP_AO_INFO, &info);
573 info.set_current = 1;
574 info.set_rnext = 1;
575 info.current_key = 100;
576 info.rnext = 100;
577 setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set current+rnext key");
578
579 sk = prepare_defs(TCP_AO_INFO, &info);
580 info.set_counters = 1;
581 info.pkt_good = 321;
582 info.pkt_bad = 888;
583 info.pkt_key_not_found = 654;
584 info.pkt_ao_required = 987654;
585 info.pkt_dropped_icmp = 10000;
586 setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set counters");
587
588 sk = prepare_defs(TCP_AO_INFO, &info);
589 setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "no-op");
590 }
591
getsockopt_checked(int sk,struct tcp_ao_getsockopt * optval,int err,const char * tst)592 static void getsockopt_checked(int sk, struct tcp_ao_getsockopt *optval,
593 int err, const char *tst)
594 {
595 socklen_t len = sizeof(struct tcp_ao_getsockopt);
596
597 __setsockopt_checked(sk, TCP_AO_GET_KEYS, true, optval, &len, err,
598 "get keys: ", tst);
599 }
600
test_einval_get_keys(void)601 static void test_einval_get_keys(void)
602 {
603 struct tcp_ao_getsockopt out;
604 int sk;
605
606 sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
607 if (sk < 0)
608 test_error("socket()");
609 getsockopt_checked(sk, &out, ENOENT, "no ao_info");
610
611 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
612 getsockopt_checked(sk, &out, 0, "proper tcp_ao_get_mkts()");
613
614 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
615 out.pkt_good = 643;
616 getsockopt_checked(sk, &out, EINVAL, "set out-only pkt_good counter");
617
618 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
619 out.pkt_bad = 94;
620 getsockopt_checked(sk, &out, EINVAL, "set out-only pkt_bad counter");
621
622 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
623 out.keyflags = (uint8_t)(-1);
624 getsockopt_checked(sk, &out, EINVAL, "bad keyflags");
625
626 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
627 out.ifindex = 42;
628 getsockopt_checked(sk, &out, EINVAL,
629 "ifindex without TCP_AO_KEYF_IFNINDEX");
630
631 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
632 out.reserved = 1;
633 getsockopt_checked(sk, &out, EINVAL, "using reserved field");
634
635 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
636 out.get_all = 0;
637 out.prefix = 0;
638 tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);
639 getsockopt_checked(sk, &out, EINVAL, "no prefix, addr");
640
641 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
642 out.get_all = 0;
643 out.prefix = 0;
644 memcpy(&out.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
645 getsockopt_checked(sk, &out, 0, "no prefix, any addr");
646
647 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
648 out.get_all = 0;
649 out.prefix = 32;
650 memcpy(&out.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
651 getsockopt_checked(sk, &out, EINVAL, "prefix, any addr");
652
653 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
654 out.get_all = 0;
655 out.prefix = 129;
656 tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);
657 getsockopt_checked(sk, &out, EINVAL, "too big prefix");
658
659 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
660 out.get_all = 0;
661 out.prefix = 2;
662 tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);
663 getsockopt_checked(sk, &out, EINVAL, "too short prefix");
664
665 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
666 out.get_all = 0;
667 out.prefix = DEFAULT_TEST_PREFIX;
668 tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);
669 getsockopt_checked(sk, &out, 0, "prefix + addr");
670
671 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
672 out.get_all = 1;
673 out.prefix = DEFAULT_TEST_PREFIX;
674 getsockopt_checked(sk, &out, EINVAL, "get_all + prefix");
675
676 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
677 out.get_all = 1;
678 tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);
679 getsockopt_checked(sk, &out, EINVAL, "get_all + addr");
680
681 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
682 out.get_all = 1;
683 out.sndid = 1;
684 getsockopt_checked(sk, &out, EINVAL, "get_all + sndid");
685
686 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
687 out.get_all = 1;
688 out.rcvid = 1;
689 getsockopt_checked(sk, &out, EINVAL, "get_all + rcvid");
690
691 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
692 out.get_all = 0;
693 out.is_current = 1;
694 out.prefix = DEFAULT_TEST_PREFIX;
695 getsockopt_checked(sk, &out, EINVAL, "current + prefix");
696
697 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
698 out.get_all = 0;
699 out.is_current = 1;
700 tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);
701 getsockopt_checked(sk, &out, EINVAL, "current + addr");
702
703 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
704 out.get_all = 0;
705 out.is_current = 1;
706 out.sndid = 1;
707 getsockopt_checked(sk, &out, EINVAL, "current + sndid");
708
709 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
710 out.get_all = 0;
711 out.is_current = 1;
712 out.rcvid = 1;
713 getsockopt_checked(sk, &out, EINVAL, "current + rcvid");
714
715 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
716 out.get_all = 0;
717 out.is_rnext = 1;
718 out.prefix = DEFAULT_TEST_PREFIX;
719 getsockopt_checked(sk, &out, EINVAL, "rnext + prefix");
720
721 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
722 out.get_all = 0;
723 out.is_rnext = 1;
724 tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);
725 getsockopt_checked(sk, &out, EINVAL, "rnext + addr");
726
727 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
728 out.get_all = 0;
729 out.is_rnext = 1;
730 out.sndid = 1;
731 getsockopt_checked(sk, &out, EINVAL, "rnext + sndid");
732
733 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
734 out.get_all = 0;
735 out.is_rnext = 1;
736 out.rcvid = 1;
737 getsockopt_checked(sk, &out, EINVAL, "rnext + rcvid");
738
739 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
740 out.get_all = 1;
741 out.is_current = 1;
742 getsockopt_checked(sk, &out, EINVAL, "get_all + current");
743
744 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
745 out.get_all = 1;
746 out.is_rnext = 1;
747 getsockopt_checked(sk, &out, EINVAL, "get_all + rnext");
748
749 sk = prepare_defs(TCP_AO_GET_KEYS, &out);
750 out.get_all = 0;
751 out.is_current = 1;
752 out.is_rnext = 1;
753 getsockopt_checked(sk, &out, 0, "current + rnext");
754 }
755
einval_tests(void)756 static void einval_tests(void)
757 {
758 test_einval_add_key();
759 test_einval_del_key();
760 test_einval_ao_info();
761 test_einval_get_keys();
762 }
763
duplicate_tests(void)764 static void duplicate_tests(void)
765 {
766 union tcp_addr network_dup;
767 struct tcp_ao_add ao, ao2;
768 int sk;
769
770 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
771 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
772 test_error("setsockopt()");
773 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: full copy");
774
775 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
776 ao2 = ao;
777 memcpy(&ao2.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
778 ao2.prefix = 0;
779 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao2, sizeof(ao)))
780 test_error("setsockopt()");
781 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: any addr key on the socket");
782
783 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
784 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
785 test_error("setsockopt()");
786 memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
787 ao.prefix = 0;
788 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: add any addr key");
789
790 if (inet_pton(TEST_FAMILY, TEST_NETWORK, &network_dup) != 1)
791 test_error("Can't convert ip address %s", TEST_NETWORK);
792 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
793 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
794 test_error("setsockopt()");
795 if (test_prepare_def_key(&ao, "password", 0, network_dup,
796 16, 0, 100, 100))
797 test_error("prepare default tcp_ao_add");
798 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: add any addr for the same subnet");
799
800 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
801 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
802 test_error("setsockopt()");
803 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: full copy of a key");
804
805 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
806 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
807 test_error("setsockopt()");
808 ao.rcvid = 101;
809 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: RecvID differs");
810
811 sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
812 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
813 test_error("setsockopt()");
814 ao.sndid = 101;
815 setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: SendID differs");
816 }
817
fetch_all_keys(int sk,struct tcp_ao_getsockopt * keys)818 static void fetch_all_keys(int sk, struct tcp_ao_getsockopt *keys)
819 {
820 socklen_t optlen = sizeof(struct tcp_ao_getsockopt);
821
822 memset(keys, 0, sizeof(struct tcp_ao_getsockopt) * FILTER_TEST_NKEYS);
823 keys[0].get_all = 1;
824 keys[0].nkeys = FILTER_TEST_NKEYS;
825 if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, &keys[0], &optlen))
826 test_error("getsockopt");
827 }
828
prepare_test_keys(struct tcp_ao_getsockopt * keys)829 static int prepare_test_keys(struct tcp_ao_getsockopt *keys)
830 {
831 const char *test_password = "Test password number ";
832 struct tcp_ao_add test_ao[FILTER_TEST_NKEYS];
833 char test_password_scratch[64] = {};
834 u8 rcvid = 100, sndid = 100;
835 int sk;
836
837 sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
838 if (sk < 0)
839 test_error("socket()");
840
841 for (int i = 0; i < FILTER_TEST_NKEYS; i++) {
842 snprintf(test_password_scratch, 64, "%s %d", test_password, i);
843 test_prepare_key(&test_ao[i], DEFAULT_TEST_ALGO, this_ip_dest,
844 false, false, DEFAULT_TEST_PREFIX, 0, sndid++,
845 rcvid++, 0, 0, strlen(test_password_scratch),
846 test_password_scratch);
847 }
848 test_ao[0].set_current = 1;
849 test_ao[1].set_rnext = 1;
850 /* One key with a different addr and overlapping sndid, rcvid */
851 tcp_addr_to_sockaddr_in(&test_ao[2].addr, &this_ip_addr, 0);
852 test_ao[2].sndid = 100;
853 test_ao[2].rcvid = 100;
854
855 /* Add keys in a random order */
856 for (int i = 0; i < FILTER_TEST_NKEYS; i++) {
857 int randidx = rand() % (FILTER_TEST_NKEYS - i);
858
859 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY,
860 &test_ao[randidx], sizeof(struct tcp_ao_add)))
861 test_error("setsockopt()");
862 memcpy(&test_ao[randidx], &test_ao[FILTER_TEST_NKEYS - 1 - i],
863 sizeof(struct tcp_ao_add));
864 }
865
866 fetch_all_keys(sk, keys);
867
868 return sk;
869 }
870
871 /* Assumes passwords are unique */
compare_mkts(struct tcp_ao_getsockopt * expected,int nexpected,struct tcp_ao_getsockopt * actual,int nactual)872 static int compare_mkts(struct tcp_ao_getsockopt *expected, int nexpected,
873 struct tcp_ao_getsockopt *actual, int nactual)
874 {
875 int matches = 0;
876
877 for (int i = 0; i < nexpected; i++) {
878 for (int j = 0; j < nactual; j++) {
879 if (memcmp(expected[i].key, actual[j].key,
880 TCP_AO_MAXKEYLEN) == 0)
881 matches++;
882 }
883 }
884 return nexpected - matches;
885 }
886
filter_keys_checked(int sk,struct tcp_ao_getsockopt * filter,struct tcp_ao_getsockopt * expected,unsigned int nexpected,const char * tst)887 static void filter_keys_checked(int sk, struct tcp_ao_getsockopt *filter,
888 struct tcp_ao_getsockopt *expected,
889 unsigned int nexpected, const char *tst)
890 {
891 struct tcp_ao_getsockopt filtered_keys[FILTER_TEST_NKEYS] = {};
892 struct tcp_ao_getsockopt all_keys[FILTER_TEST_NKEYS] = {};
893 socklen_t len = sizeof(struct tcp_ao_getsockopt);
894
895 fetch_all_keys(sk, all_keys);
896 memcpy(&filtered_keys[0], filter, sizeof(struct tcp_ao_getsockopt));
897 filtered_keys[0].nkeys = FILTER_TEST_NKEYS;
898 if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, filtered_keys, &len))
899 test_error("getsockopt");
900 if (filtered_keys[0].nkeys != nexpected) {
901 test_fail("wrong nr of keys, expected %u got %u", nexpected,
902 filtered_keys[0].nkeys);
903 goto out_close;
904 }
905 if (compare_mkts(expected, nexpected, filtered_keys,
906 filtered_keys[0].nkeys)) {
907 test_fail("got wrong keys back");
908 goto out_close;
909 }
910 test_ok("filter keys: %s", tst);
911
912 out_close:
913 close(sk);
914 memset(filter, 0, sizeof(struct tcp_ao_getsockopt));
915 }
916
filter_tests(void)917 static void filter_tests(void)
918 {
919 struct tcp_ao_getsockopt original_keys[FILTER_TEST_NKEYS];
920 struct tcp_ao_getsockopt expected_keys[FILTER_TEST_NKEYS];
921 struct tcp_ao_getsockopt filter = {};
922 int sk, f, nmatches;
923 socklen_t len;
924
925 f = 2;
926 sk = prepare_test_keys(original_keys);
927 filter.rcvid = original_keys[f].rcvid;
928 filter.sndid = original_keys[f].sndid;
929 memcpy(&filter.addr, &original_keys[f].addr,
930 sizeof(original_keys[f].addr));
931 filter.prefix = original_keys[f].prefix;
932 filter_keys_checked(sk, &filter, &original_keys[f], 1,
933 "by sndid, rcvid, address");
934
935 f = -1;
936 sk = prepare_test_keys(original_keys);
937 for (int i = 0; i < original_keys[0].nkeys; i++) {
938 if (original_keys[i].is_current) {
939 f = i;
940 break;
941 }
942 }
943 if (f < 0)
944 test_error("No current key after adding one");
945 filter.is_current = 1;
946 filter_keys_checked(sk, &filter, &original_keys[f], 1, "by is_current");
947
948 f = -1;
949 sk = prepare_test_keys(original_keys);
950 for (int i = 0; i < original_keys[0].nkeys; i++) {
951 if (original_keys[i].is_rnext) {
952 f = i;
953 break;
954 }
955 }
956 if (f < 0)
957 test_error("No rnext key after adding one");
958 filter.is_rnext = 1;
959 filter_keys_checked(sk, &filter, &original_keys[f], 1, "by is_rnext");
960
961 f = -1;
962 nmatches = 0;
963 sk = prepare_test_keys(original_keys);
964 for (int i = 0; i < original_keys[0].nkeys; i++) {
965 if (original_keys[i].sndid == 100) {
966 f = i;
967 memcpy(&expected_keys[nmatches], &original_keys[i],
968 sizeof(struct tcp_ao_getsockopt));
969 nmatches++;
970 }
971 }
972 if (f < 0)
973 test_error("No key for sndid 100");
974 if (nmatches != 2)
975 test_error("Should have 2 keys with sndid 100");
976 filter.rcvid = original_keys[f].rcvid;
977 filter.sndid = original_keys[f].sndid;
978 filter.addr.ss_family = test_family;
979 filter_keys_checked(sk, &filter, expected_keys, nmatches,
980 "by sndid, rcvid");
981
982 sk = prepare_test_keys(original_keys);
983 filter.get_all = 1;
984 filter.nkeys = FILTER_TEST_NKEYS / 2;
985 len = sizeof(struct tcp_ao_getsockopt);
986 if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, &filter, &len))
987 test_error("getsockopt");
988 if (filter.nkeys == FILTER_TEST_NKEYS)
989 test_ok("filter keys: correct nkeys when in.nkeys < matches");
990 else
991 test_fail("filter keys: wrong nkeys, expected %u got %u",
992 FILTER_TEST_NKEYS, filter.nkeys);
993 }
994
client_fn(void * arg)995 static void *client_fn(void *arg)
996 {
997 if (inet_pton(TEST_FAMILY, __TEST_CLIENT_IP(2), &tcp_md5_client) != 1)
998 test_error("Can't convert ip address");
999 extend_tests();
1000 einval_tests();
1001 filter_tests();
1002 duplicate_tests();
1003
1004 return NULL;
1005 }
1006
main(int argc,char * argv[])1007 int main(int argc, char *argv[])
1008 {
1009 test_init(126, client_fn, NULL);
1010 return 0;
1011 }
1012