xref: /linux/tools/testing/selftests/net/tcp_ao/unsigned-md5.c (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
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