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