1 // SPDX-License-Identifier: GPL-2.0
2 /* Author: Dmitry Safonov <dima@arista.com> */
3 #include <inttypes.h>
4 #include "aolib.h"
5
6 #define fault(type) (inj == FAULT_ ## type)
7 static const char *md5_password = "Some evil genius, enemy to mankind, must have been the first contriver.";
8 static const char *ao_password = DEFAULT_TEST_PASSWORD;
9 static volatile int sk_pair;
10
11 static union tcp_addr client2;
12 static union tcp_addr client3;
13
14 static const int test_vrf_ifindex = 200;
15 static const uint8_t test_vrf_tabid = 42;
setup_vrfs(void)16 static void setup_vrfs(void)
17 {
18 int err;
19
20 if (!kernel_config_has(KCONFIG_NET_VRF))
21 return;
22
23 err = add_vrf("ksft-vrf", test_vrf_tabid, test_vrf_ifindex, -1);
24 if (err)
25 test_error("Failed to add a VRF: %d", err);
26
27 err = link_set_up("ksft-vrf");
28 if (err)
29 test_error("Failed to bring up a VRF");
30
31 err = ip_route_add_vrf(veth_name, TEST_FAMILY,
32 this_ip_addr, this_ip_dest, test_vrf_tabid);
33 if (err)
34 test_error("Failed to add a route to VRF: %d", err);
35 }
36
try_accept(const char * tst_name,unsigned int port,union tcp_addr * md5_addr,uint8_t md5_prefix,union tcp_addr * ao_addr,uint8_t ao_prefix,bool set_ao_required,uint8_t sndid,uint8_t rcvid,uint8_t vrf,const char * cnt_name,test_cnt cnt_expected,int needs_tcp_md5,fault_t inj)37 static void try_accept(const char *tst_name, unsigned int port,
38 union tcp_addr *md5_addr, uint8_t md5_prefix,
39 union tcp_addr *ao_addr, uint8_t ao_prefix,
40 bool set_ao_required,
41 uint8_t sndid, uint8_t rcvid, uint8_t vrf,
42 const char *cnt_name, test_cnt cnt_expected,
43 int needs_tcp_md5, fault_t inj)
44 {
45 struct tcp_counters cnt1, cnt2;
46 uint64_t before_cnt = 0, after_cnt = 0; /* silence GCC */
47 test_cnt poll_cnt = (cnt_expected == TEST_CNT_GOOD) ? 0 : cnt_expected;
48 int lsk, err, sk = -1;
49
50 if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
51 return;
52
53 lsk = test_listen_socket(this_ip_addr, port, 1);
54
55 if (md5_addr && test_set_md5(lsk, *md5_addr, md5_prefix, -1, md5_password))
56 test_error("setsockopt(TCP_MD5SIG_EXT)");
57
58 if (ao_addr && test_add_key(lsk, ao_password,
59 *ao_addr, ao_prefix, sndid, rcvid))
60 test_error("setsockopt(TCP_AO_ADD_KEY)");
61
62 if (set_ao_required && test_set_ao_flags(lsk, true, false))
63 test_error("setsockopt(TCP_AO_INFO)");
64
65 if (cnt_name)
66 before_cnt = netstat_get_one(cnt_name, NULL);
67 if (ao_addr && test_get_tcp_counters(lsk, &cnt1))
68 test_error("test_get_tcp_counters()");
69
70 synchronize_threads(); /* preparations done */
71
72 err = test_skpair_wait_poll(lsk, 0, poll_cnt, &sk_pair);
73 synchronize_threads(); /* connect()/accept() timeouts */
74 if (err == -ETIMEDOUT) {
75 sk_pair = err;
76 if (!fault(TIMEOUT))
77 test_fail("%s: timed out for accept()", tst_name);
78 } else if (err == -EKEYREJECTED) {
79 if (!fault(KEYREJECT))
80 test_fail("%s: key was rejected", tst_name);
81 } else if (err < 0) {
82 test_error("test_skpair_wait_poll()");
83 } else {
84 if (fault(TIMEOUT))
85 test_fail("%s: ready to accept", tst_name);
86
87 sk = accept(lsk, NULL, NULL);
88 if (sk < 0) {
89 test_error("accept()");
90 } else {
91 if (fault(TIMEOUT))
92 test_fail("%s: accepted", tst_name);
93 }
94 }
95
96 if (ao_addr && test_get_tcp_counters(lsk, &cnt2))
97 test_error("test_get_tcp_counters()");
98 close(lsk);
99
100 if (!cnt_name) {
101 test_ok("%s: no counter checks", tst_name);
102 goto out;
103 }
104
105 after_cnt = netstat_get_one(cnt_name, NULL);
106
107 if (after_cnt <= before_cnt) {
108 test_fail("%s: %s counter did not increase: %" PRIu64 " <= %" PRIu64,
109 tst_name, cnt_name, after_cnt, before_cnt);
110 } else {
111 test_ok("%s: counter %s increased %" PRIu64 " => %" PRIu64,
112 tst_name, cnt_name, before_cnt, after_cnt);
113 }
114 if (ao_addr)
115 test_assert_counters(tst_name, &cnt1, &cnt2, cnt_expected);
116
117 out:
118 synchronize_threads(); /* test_kill_sk() */
119 if (sk >= 0)
120 test_kill_sk(sk);
121 }
122
server_add_routes(void)123 static void server_add_routes(void)
124 {
125 int family = TEST_FAMILY;
126
127 synchronize_threads(); /* client_add_ips() */
128
129 if (ip_route_add(veth_name, family, this_ip_addr, client2))
130 test_error("Failed to add route");
131 if (ip_route_add(veth_name, family, this_ip_addr, client3))
132 test_error("Failed to add route");
133 }
134
server_add_fail_tests(unsigned int * port)135 static void server_add_fail_tests(unsigned int *port)
136 {
137 union tcp_addr addr_any = {};
138
139 try_accept("TCP-AO established: add TCP-MD5 key", (*port)++, NULL, 0,
140 &addr_any, 0, 0, 100, 100, 0, "TCPAOGood", TEST_CNT_GOOD,
141 1, 0);
142 try_accept("TCP-MD5 established: add TCP-AO key", (*port)++, &addr_any,
143 0, NULL, 0, 0, 0, 0, 0, NULL, 0, 1, 0);
144 try_accept("non-signed established: add TCP-AO key", (*port)++, NULL, 0,
145 NULL, 0, 0, 0, 0, 0, "CurrEstab", 0, 0, 0);
146 }
147
server_vrf_tests(unsigned int * port)148 static void server_vrf_tests(unsigned int *port)
149 {
150 setup_vrfs();
151 }
152
server_fn(void * arg)153 static void *server_fn(void *arg)
154 {
155 unsigned int port = test_server_port;
156 union tcp_addr addr_any = {};
157
158 server_add_routes();
159
160 try_accept("[server] AO server (INADDR_ANY): AO client", port++, NULL, 0,
161 &addr_any, 0, 0, 100, 100, 0, "TCPAOGood",
162 TEST_CNT_GOOD, 0, 0);
163 try_accept("[server] AO server (INADDR_ANY): MD5 client", port++, NULL, 0,
164 &addr_any, 0, 0, 100, 100, 0, "TCPMD5Unexpected",
165 TEST_CNT_NS_MD5_UNEXPECTED, 1, FAULT_TIMEOUT);
166 try_accept("[server] AO server (INADDR_ANY): no sign client", port++, NULL, 0,
167 &addr_any, 0, 0, 100, 100, 0, "TCPAORequired",
168 TEST_CNT_AO_REQUIRED, 0, FAULT_TIMEOUT);
169 try_accept("[server] AO server (AO_REQUIRED): AO client", port++, NULL, 0,
170 &this_ip_dest, TEST_PREFIX, true,
171 100, 100, 0, "TCPAOGood", TEST_CNT_GOOD, 0, 0);
172 try_accept("[server] AO server (AO_REQUIRED): unsigned client", port++, NULL, 0,
173 &this_ip_dest, TEST_PREFIX, true,
174 100, 100, 0, "TCPAORequired",
175 TEST_CNT_AO_REQUIRED, 0, FAULT_TIMEOUT);
176
177 try_accept("[server] MD5 server (INADDR_ANY): AO client", port++, &addr_any, 0,
178 NULL, 0, 0, 0, 0, 0, "TCPAOKeyNotFound",
179 TEST_CNT_NS_KEY_NOT_FOUND, 1, FAULT_TIMEOUT);
180 try_accept("[server] MD5 server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
181 NULL, 0, 0, 0, 0, 0, NULL, 0, 1, 0);
182 try_accept("[server] MD5 server (INADDR_ANY): no sign client", port++, &addr_any,
183 0, NULL, 0, 0, 0, 0, 0, "TCPMD5NotFound",
184 TEST_CNT_NS_MD5_NOT_FOUND, 1, FAULT_TIMEOUT);
185
186 try_accept("[server] no sign server: AO client", port++, NULL, 0,
187 NULL, 0, 0, 0, 0, 0, "TCPAOKeyNotFound",
188 TEST_CNT_NS_KEY_NOT_FOUND, 0, FAULT_TIMEOUT);
189 try_accept("[server] no sign server: MD5 client", port++, NULL, 0,
190 NULL, 0, 0, 0, 0, 0, "TCPMD5Unexpected",
191 TEST_CNT_NS_MD5_UNEXPECTED, 1, FAULT_TIMEOUT);
192 try_accept("[server] no sign server: no sign client", port++, NULL, 0,
193 NULL, 0, 0, 0, 0, 0, "CurrEstab", 0, 0, 0);
194
195 try_accept("[server] AO+MD5 server: AO client (matching)", port++,
196 &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
197 100, 100, 0, "TCPAOGood", TEST_CNT_GOOD, 1, 0);
198 try_accept("[server] AO+MD5 server: AO client (misconfig, matching MD5)", port++,
199 &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
200 100, 100, 0, "TCPAOKeyNotFound", TEST_CNT_AO_KEY_NOT_FOUND,
201 1, FAULT_TIMEOUT);
202 try_accept("[server] AO+MD5 server: AO client (misconfig, non-matching)", port++,
203 &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
204 100, 100, 0, "TCPAOKeyNotFound", TEST_CNT_AO_KEY_NOT_FOUND,
205 1, FAULT_TIMEOUT);
206 try_accept("[server] AO+MD5 server: MD5 client (matching)", port++,
207 &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
208 100, 100, 0, NULL, 0, 1, 0);
209 try_accept("[server] AO+MD5 server: MD5 client (misconfig, matching AO)", port++,
210 &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
211 100, 100, 0, "TCPMD5Unexpected",
212 TEST_CNT_NS_MD5_UNEXPECTED, 1, FAULT_TIMEOUT);
213 try_accept("[server] AO+MD5 server: MD5 client (misconfig, non-matching)", port++,
214 &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
215 100, 100, 0, "TCPMD5Unexpected",
216 TEST_CNT_NS_MD5_UNEXPECTED, 1, FAULT_TIMEOUT);
217 try_accept("[server] AO+MD5 server: no sign client (unmatched)", port++,
218 &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
219 100, 100, 0, "CurrEstab", 0, 1, 0);
220 try_accept("[server] AO+MD5 server: no sign client (misconfig, matching AO)",
221 port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
222 100, 100, 0, "TCPAORequired",
223 TEST_CNT_AO_REQUIRED, 1, FAULT_TIMEOUT);
224 try_accept("[server] AO+MD5 server: no sign client (misconfig, matching MD5)",
225 port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
226 100, 100, 0, "TCPMD5NotFound",
227 TEST_CNT_NS_MD5_NOT_FOUND, 1, FAULT_TIMEOUT);
228
229 /* Key rejected by the other side, failing short through skpair */
230 try_accept("[server] AO+MD5 server: client with both [TCP-MD5] and TCP-AO keys",
231 port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
232 100, 100, 0, NULL, 0, 1, FAULT_KEYREJECT);
233 try_accept("[server] AO+MD5 server: client with both TCP-MD5 and [TCP-AO] keys",
234 port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
235 100, 100, 0, NULL, 0, 1, FAULT_KEYREJECT);
236
237 server_add_fail_tests(&port);
238
239 server_vrf_tests(&port);
240
241 /* client exits */
242 synchronize_threads();
243 return NULL;
244 }
245
client_bind(int sk,union tcp_addr bind_addr)246 static int client_bind(int sk, union tcp_addr bind_addr)
247 {
248 #ifdef IPV6_TEST
249 struct sockaddr_in6 addr = {
250 .sin6_family = AF_INET6,
251 .sin6_port = 0,
252 .sin6_addr = bind_addr.a6,
253 };
254 #else
255 struct sockaddr_in addr = {
256 .sin_family = AF_INET,
257 .sin_port = 0,
258 .sin_addr = bind_addr.a4,
259 };
260 #endif
261 return bind(sk, &addr, sizeof(addr));
262 }
263
try_connect(const char * tst_name,unsigned int port,union tcp_addr * md5_addr,uint8_t md5_prefix,union tcp_addr * ao_addr,uint8_t ao_prefix,uint8_t sndid,uint8_t rcvid,uint8_t vrf,fault_t inj,int needs_tcp_md5,union tcp_addr * bind_addr)264 static void try_connect(const char *tst_name, unsigned int port,
265 union tcp_addr *md5_addr, uint8_t md5_prefix,
266 union tcp_addr *ao_addr, uint8_t ao_prefix,
267 uint8_t sndid, uint8_t rcvid, uint8_t vrf,
268 fault_t inj, int needs_tcp_md5, union tcp_addr *bind_addr)
269 {
270 int sk, ret;
271
272 if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
273 return;
274
275 sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
276 if (sk < 0)
277 test_error("socket()");
278
279 if (bind_addr && client_bind(sk, *bind_addr))
280 test_error("bind()");
281
282 if (md5_addr && test_set_md5(sk, *md5_addr, md5_prefix, -1, md5_password))
283 test_error("setsockopt(TCP_MD5SIG_EXT)");
284
285 if (ao_addr && test_add_key(sk, ao_password, *ao_addr,
286 ao_prefix, sndid, rcvid))
287 test_error("setsockopt(TCP_AO_ADD_KEY)");
288
289 synchronize_threads(); /* preparations done */
290
291 ret = test_skpair_connect_poll(sk, this_ip_dest, port, 0, &sk_pair);
292 synchronize_threads(); /* connect()/accept() timeouts */
293 if (ret < 0) {
294 sk_pair = ret;
295 if (fault(KEYREJECT) && ret == -EKEYREJECTED)
296 test_ok("%s: connect() was prevented", tst_name);
297 else if (ret == -ETIMEDOUT && fault(TIMEOUT))
298 test_ok("%s", tst_name);
299 else if (ret == -ECONNREFUSED &&
300 (fault(TIMEOUT) || fault(KEYREJECT)))
301 test_ok("%s: refused to connect", tst_name);
302 else
303 test_error("%s: connect() returned %d", tst_name, ret);
304 goto out;
305 }
306
307 if (fault(TIMEOUT) || fault(KEYREJECT))
308 test_fail("%s: connected", tst_name);
309 else
310 test_ok("%s: connected", tst_name);
311
312 out:
313 synchronize_threads(); /* test_kill_sk() */
314 if (ret > 0) /* test_skpair_connect_poll() cleans up on failure */
315 test_kill_sk(sk);
316 }
317
318 #define PREINSTALL_MD5_FIRST BIT(0)
319 #define PREINSTALL_AO BIT(1)
320 #define POSTINSTALL_AO BIT(2)
321 #define PREINSTALL_MD5 BIT(3)
322 #define POSTINSTALL_MD5 BIT(4)
323
try_add_key_vrf(int sk,union tcp_addr in_addr,uint8_t prefix,int vrf,uint8_t sndid,uint8_t rcvid,bool set_ao_required)324 static int try_add_key_vrf(int sk, union tcp_addr in_addr, uint8_t prefix,
325 int vrf, uint8_t sndid, uint8_t rcvid,
326 bool set_ao_required)
327 {
328 uint8_t keyflags = 0;
329
330 if (vrf >= 0)
331 keyflags |= TCP_AO_KEYF_IFINDEX;
332 else
333 vrf = 0;
334 if (set_ao_required) {
335 int err = test_set_ao_flags(sk, true, 0);
336
337 if (err)
338 return err;
339 }
340 return test_add_key_vrf(sk, ao_password, keyflags, in_addr, prefix,
341 (uint8_t)vrf, sndid, rcvid);
342 }
343
test_continue(const char * tst_name,int err,fault_t inj,bool added_ao)344 static bool test_continue(const char *tst_name, int err,
345 fault_t inj, bool added_ao)
346 {
347 bool expected_to_fail;
348
349 expected_to_fail = fault(PREINSTALL_AO) && added_ao;
350 expected_to_fail |= fault(PREINSTALL_MD5) && !added_ao;
351
352 if (!err) {
353 if (!expected_to_fail)
354 return true;
355 test_fail("%s: setsockopt()s were expected to fail", tst_name);
356 return false;
357 }
358 if (err != -EKEYREJECTED || !expected_to_fail) {
359 test_error("%s: setsockopt(%s) = %d", tst_name,
360 added_ao ? "TCP_AO_ADD_KEY" : "TCP_MD5SIG_EXT", err);
361 return false;
362 }
363 test_ok("%s: prefailed as expected: %m", tst_name);
364 return false;
365 }
366
open_add(const char * tst_name,unsigned int port,unsigned int strategy,union tcp_addr md5_addr,uint8_t md5_prefix,int md5_vrf,union tcp_addr ao_addr,uint8_t ao_prefix,int ao_vrf,bool set_ao_required,uint8_t sndid,uint8_t rcvid,fault_t inj)367 static int open_add(const char *tst_name, unsigned int port,
368 unsigned int strategy,
369 union tcp_addr md5_addr, uint8_t md5_prefix, int md5_vrf,
370 union tcp_addr ao_addr, uint8_t ao_prefix,
371 int ao_vrf, bool set_ao_required,
372 uint8_t sndid, uint8_t rcvid,
373 fault_t inj)
374 {
375 int sk;
376
377 sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
378 if (sk < 0)
379 test_error("socket()");
380
381 if (client_bind(sk, this_ip_addr))
382 test_error("bind()");
383
384 if (strategy & PREINSTALL_MD5_FIRST) {
385 if (test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password))
386 test_error("setsockopt(TCP_MD5SIG_EXT)");
387 }
388
389 if (strategy & PREINSTALL_AO) {
390 int err = try_add_key_vrf(sk, ao_addr, ao_prefix, ao_vrf,
391 sndid, rcvid, set_ao_required);
392
393 if (!test_continue(tst_name, err, inj, true)) {
394 close(sk);
395 return -1;
396 }
397 }
398
399 if (strategy & PREINSTALL_MD5) {
400 errno = 0;
401 test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password);
402 if (!test_continue(tst_name, -errno, inj, false)) {
403 close(sk);
404 return -1;
405 }
406 }
407
408 return sk;
409 }
410
try_to_preadd(const char * tst_name,unsigned int port,unsigned int strategy,union tcp_addr md5_addr,uint8_t md5_prefix,int md5_vrf,union tcp_addr ao_addr,uint8_t ao_prefix,int ao_vrf,bool set_ao_required,uint8_t sndid,uint8_t rcvid,int needs_tcp_md5,int needs_vrf,fault_t inj)411 static void try_to_preadd(const char *tst_name, unsigned int port,
412 unsigned int strategy,
413 union tcp_addr md5_addr, uint8_t md5_prefix,
414 int md5_vrf,
415 union tcp_addr ao_addr, uint8_t ao_prefix,
416 int ao_vrf, bool set_ao_required,
417 uint8_t sndid, uint8_t rcvid,
418 int needs_tcp_md5, int needs_vrf, fault_t inj)
419 {
420 int sk;
421
422 if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
423 return;
424 if (needs_vrf && should_skip_test(tst_name, KCONFIG_NET_VRF))
425 return;
426
427 sk = open_add(tst_name, port, strategy, md5_addr, md5_prefix, md5_vrf,
428 ao_addr, ao_prefix, ao_vrf, set_ao_required,
429 sndid, rcvid, inj);
430 if (sk < 0)
431 return;
432
433 test_ok("%s", tst_name);
434 close(sk);
435 }
436
try_to_add(const char * tst_name,unsigned int port,unsigned int strategy,union tcp_addr md5_addr,uint8_t md5_prefix,int md5_vrf,union tcp_addr ao_addr,uint8_t ao_prefix,int ao_vrf,uint8_t sndid,uint8_t rcvid,int needs_tcp_md5,fault_t inj)437 static void try_to_add(const char *tst_name, unsigned int port,
438 unsigned int strategy,
439 union tcp_addr md5_addr, uint8_t md5_prefix,
440 int md5_vrf,
441 union tcp_addr ao_addr, uint8_t ao_prefix,
442 int ao_vrf, uint8_t sndid, uint8_t rcvid,
443 int needs_tcp_md5, fault_t inj)
444 {
445 int sk, ret;
446
447 if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
448 return;
449
450 sk = open_add(tst_name, port, strategy, md5_addr, md5_prefix, md5_vrf,
451 ao_addr, ao_prefix, ao_vrf, 0, sndid, rcvid, inj);
452 if (sk < 0)
453 return;
454
455 synchronize_threads(); /* preparations done */
456
457 ret = test_skpair_connect_poll(sk, this_ip_dest, port, 0, &sk_pair);
458
459 synchronize_threads(); /* connect()/accept() timeouts */
460 if (ret < 0) {
461 test_error("%s: connect() returned %d", tst_name, ret);
462 goto out;
463 }
464
465 if (strategy & POSTINSTALL_MD5) {
466 if (test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password)) {
467 if (fault(POSTINSTALL)) {
468 test_ok("%s: postfailed as expected", tst_name);
469 goto out;
470 } else {
471 test_error("setsockopt(TCP_MD5SIG_EXT)");
472 }
473 } else if (fault(POSTINSTALL)) {
474 test_fail("%s: post setsockopt() was expected to fail", tst_name);
475 goto out;
476 }
477 }
478
479 if (strategy & POSTINSTALL_AO) {
480 if (try_add_key_vrf(sk, ao_addr, ao_prefix, ao_vrf,
481 sndid, rcvid, 0)) {
482 if (fault(POSTINSTALL)) {
483 test_ok("%s: postfailed as expected", tst_name);
484 goto out;
485 } else {
486 test_error("setsockopt(TCP_AO_ADD_KEY)");
487 }
488 } else if (fault(POSTINSTALL)) {
489 test_fail("%s: post setsockopt() was expected to fail", tst_name);
490 goto out;
491 }
492 }
493
494 out:
495 synchronize_threads(); /* test_kill_sk() */
496 if (ret > 0) /* test_skpair_connect_poll() cleans up on failure */
497 test_kill_sk(sk);
498 }
499
client_add_ip(union tcp_addr * client,const char * ip)500 static void client_add_ip(union tcp_addr *client, const char *ip)
501 {
502 int err, family = TEST_FAMILY;
503
504 if (inet_pton(family, ip, client) != 1)
505 test_error("Can't convert ip address %s", ip);
506
507 err = ip_addr_add(veth_name, family, *client, TEST_PREFIX);
508 if (err)
509 test_error("Failed to add ip address: %d", err);
510 }
511
client_add_ips(void)512 static void client_add_ips(void)
513 {
514 client_add_ip(&client2, __TEST_CLIENT_IP(2));
515 client_add_ip(&client3, __TEST_CLIENT_IP(3));
516 synchronize_threads(); /* server_add_routes() */
517 }
518
client_add_fail_tests(unsigned int * port)519 static void client_add_fail_tests(unsigned int *port)
520 {
521 try_to_add("TCP-AO established: add TCP-MD5 key",
522 (*port)++, POSTINSTALL_MD5 | PREINSTALL_AO,
523 this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
524 100, 100, 1, FAULT_POSTINSTALL);
525 try_to_add("TCP-MD5 established: add TCP-AO key",
526 (*port)++, PREINSTALL_MD5 | POSTINSTALL_AO,
527 this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
528 100, 100, 1, FAULT_POSTINSTALL);
529 try_to_add("non-signed established: add TCP-AO key",
530 (*port)++, POSTINSTALL_AO,
531 this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
532 100, 100, 0, FAULT_POSTINSTALL);
533
534 try_to_add("TCP-AO key intersects with existing TCP-MD5 key",
535 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
536 this_ip_addr, TEST_PREFIX, -1, this_ip_addr, TEST_PREFIX, -1,
537 100, 100, 1, FAULT_PREINSTALL_AO);
538 try_to_add("TCP-MD5 key intersects with existing TCP-AO key",
539 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
540 this_ip_addr, TEST_PREFIX, -1, this_ip_addr, TEST_PREFIX, -1,
541 100, 100, 1, FAULT_PREINSTALL_MD5);
542
543 try_to_preadd("TCP-MD5 key + TCP-AO required",
544 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
545 this_ip_addr, TEST_PREFIX, -1,
546 this_ip_addr, TEST_PREFIX, -1, true,
547 100, 100, 1, 0, FAULT_PREINSTALL_AO);
548 try_to_preadd("TCP-AO required on socket + TCP-MD5 key",
549 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
550 this_ip_addr, TEST_PREFIX, -1,
551 this_ip_addr, TEST_PREFIX, -1, true,
552 100, 100, 1, 0, FAULT_PREINSTALL_MD5);
553 }
554
client_vrf_tests(unsigned int * port)555 static void client_vrf_tests(unsigned int *port)
556 {
557 setup_vrfs();
558
559 /* The following restrictions for setsockopt()s are expected:
560 *
561 * |--------------|-----------------|-------------|-------------|
562 * | | MD5 key without | MD5 key | MD5 key |
563 * | | l3index | l3index=0 | l3index=N |
564 * |--------------|-----------------|-------------|-------------|
565 * | TCP-AO key | | | |
566 * | without | reject | reject | reject |
567 * | l3index | | | |
568 * |--------------|-----------------|-------------|-------------|
569 * | TCP-AO key | | | |
570 * | l3index=0 | reject | reject | allow |
571 * |--------------|-----------------|-------------|-------------|
572 * | TCP-AO key | | | |
573 * | l3index=N | reject | allow | reject |
574 * |--------------|-----------------|-------------|-------------|
575 */
576 try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (no l3index)",
577 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
578 this_ip_addr, TEST_PREFIX, -1,
579 this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
580 1, 1, FAULT_PREINSTALL_MD5);
581 try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (no l3index)",
582 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
583 this_ip_addr, TEST_PREFIX, -1,
584 this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
585 1, 1, FAULT_PREINSTALL_AO);
586 try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (l3index=0)",
587 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
588 this_ip_addr, TEST_PREFIX, 0,
589 this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
590 1, 1, FAULT_PREINSTALL_MD5);
591 try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (no l3index)",
592 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
593 this_ip_addr, TEST_PREFIX, 0,
594 this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
595 1, 1, FAULT_PREINSTALL_AO);
596 try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (l3index=N)",
597 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
598 this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
599 this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
600 1, 1, FAULT_PREINSTALL_MD5);
601 try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (no l3index)",
602 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
603 this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
604 this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
605 1, 1, FAULT_PREINSTALL_AO);
606
607 try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (no l3index)",
608 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
609 this_ip_addr, TEST_PREFIX, -1,
610 this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
611 1, 1, FAULT_PREINSTALL_MD5);
612 try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (l3index=0)",
613 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
614 this_ip_addr, TEST_PREFIX, -1,
615 this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
616 1, 1, FAULT_PREINSTALL_AO);
617 try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (l3index=0)",
618 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
619 this_ip_addr, TEST_PREFIX, 0,
620 this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
621 1, 1, FAULT_PREINSTALL_MD5);
622 try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (l3index=0)",
623 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
624 this_ip_addr, TEST_PREFIX, 0,
625 this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
626 1, 1, FAULT_PREINSTALL_AO);
627 try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (l3index=N)",
628 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
629 this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
630 this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
631 1, 1, 0);
632 try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (l3index=0)",
633 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
634 this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
635 this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
636 1, 1, 0);
637
638 try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (no l3index)",
639 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
640 this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
641 this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
642 1, 1, FAULT_PREINSTALL_MD5);
643 try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (l3index=N)",
644 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
645 this_ip_addr, TEST_PREFIX, -1,
646 this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
647 1, 1, FAULT_PREINSTALL_AO);
648 try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (l3index=0)",
649 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
650 this_ip_addr, TEST_PREFIX, 0,
651 this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
652 1, 1, 0);
653 try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (l3index=N)",
654 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
655 this_ip_addr, TEST_PREFIX, 0,
656 this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
657 1, 1, 0);
658 try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (l3index=N)",
659 (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
660 this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
661 this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
662 1, 1, FAULT_PREINSTALL_MD5);
663 try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (l3index=N)",
664 (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
665 this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
666 this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
667 1, 1, FAULT_PREINSTALL_AO);
668 }
669
client_fn(void * arg)670 static void *client_fn(void *arg)
671 {
672 unsigned int port = test_server_port;
673 union tcp_addr addr_any = {};
674
675 client_add_ips();
676
677 try_connect("AO server (INADDR_ANY): AO client", port++, NULL, 0,
678 &addr_any, 0, 100, 100, 0, 0, 0, &this_ip_addr);
679 trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, this_ip_addr,
680 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
681 try_connect("AO server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
682 NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
683 trace_hash_event_expect(TCP_HASH_AO_REQUIRED, this_ip_addr,
684 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
685 try_connect("AO server (INADDR_ANY): unsigned client", port++, NULL, 0,
686 NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &this_ip_addr);
687 try_connect("AO server (AO_REQUIRED): AO client", port++, NULL, 0,
688 &addr_any, 0, 100, 100, 0, 0, 0, &this_ip_addr);
689 trace_hash_event_expect(TCP_HASH_AO_REQUIRED, client2,
690 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
691 try_connect("AO server (AO_REQUIRED): unsigned client", port++, NULL, 0,
692 NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &client2);
693
694 trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, this_ip_addr, this_ip_dest,
695 -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
696 try_connect("MD5 server (INADDR_ANY): AO client", port++, NULL, 0,
697 &addr_any, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
698 try_connect("MD5 server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
699 NULL, 0, 100, 100, 0, 0, 1, &this_ip_addr);
700 trace_hash_event_expect(TCP_HASH_MD5_REQUIRED, this_ip_addr,
701 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
702 try_connect("MD5 server (INADDR_ANY): no sign client", port++, NULL, 0,
703 NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
704
705 trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, this_ip_addr, this_ip_dest,
706 -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
707 try_connect("no sign server: AO client", port++, NULL, 0,
708 &addr_any, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &this_ip_addr);
709 trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, this_ip_addr,
710 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
711 try_connect("no sign server: MD5 client", port++, &addr_any, 0,
712 NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
713 try_connect("no sign server: no sign client", port++, NULL, 0,
714 NULL, 0, 100, 100, 0, 0, 0, &this_ip_addr);
715
716 try_connect("AO+MD5 server: AO client (matching)", port++, NULL, 0,
717 &addr_any, 0, 100, 100, 0, 0, 1, &client2);
718 trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, this_ip_addr, this_ip_dest,
719 -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
720 try_connect("AO+MD5 server: AO client (misconfig, matching MD5)",
721 port++, NULL, 0, &addr_any, 0, 100, 100, 0,
722 FAULT_TIMEOUT, 1, &this_ip_addr);
723 trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, client3, this_ip_dest,
724 -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
725 try_connect("AO+MD5 server: AO client (misconfig, non-matching)",
726 port++, NULL, 0, &addr_any, 0, 100, 100, 0,
727 FAULT_TIMEOUT, 1, &client3);
728 try_connect("AO+MD5 server: MD5 client (matching)", port++, &addr_any, 0,
729 NULL, 0, 100, 100, 0, 0, 1, &this_ip_addr);
730 trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, client2,
731 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
732 try_connect("AO+MD5 server: MD5 client (misconfig, matching AO)",
733 port++, &addr_any, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
734 1, &client2);
735 trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, client3,
736 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
737 try_connect("AO+MD5 server: MD5 client (misconfig, non-matching)",
738 port++, &addr_any, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
739 1, &client3);
740 try_connect("AO+MD5 server: no sign client (unmatched)",
741 port++, NULL, 0, NULL, 0, 100, 100, 0, 0, 1, &client3);
742 trace_hash_event_expect(TCP_HASH_AO_REQUIRED, client2,
743 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
744 try_connect("AO+MD5 server: no sign client (misconfig, matching AO)",
745 port++, NULL, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
746 1, &client2);
747 trace_hash_event_expect(TCP_HASH_MD5_REQUIRED, this_ip_addr,
748 this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
749 try_connect("AO+MD5 server: no sign client (misconfig, matching MD5)",
750 port++, NULL, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
751 1, &this_ip_addr);
752
753 try_connect("AO+MD5 server: client with both [TCP-MD5] and TCP-AO keys",
754 port++, &this_ip_addr, TEST_PREFIX,
755 &client2, TEST_PREFIX, 100, 100, 0, FAULT_KEYREJECT,
756 1, &this_ip_addr);
757 try_connect("AO+MD5 server: client with both TCP-MD5 and [TCP-AO] keys",
758 port++, &this_ip_addr, TEST_PREFIX,
759 &client2, TEST_PREFIX, 100, 100, 0, FAULT_KEYREJECT,
760 1, &client2);
761
762 client_add_fail_tests(&port);
763 client_vrf_tests(&port);
764
765 return NULL;
766 }
767
main(int argc,char * argv[])768 int main(int argc, char *argv[])
769 {
770 test_init(73, server_fn, client_fn);
771 return 0;
772 }
773