xref: /xnu-11215/tests/ipsec.m (revision 1031c584)
1#import <darwintest.h>
2#import <darwintest_utils.h>
3#import <dispatch/dispatch.h>
4#import <net/pfkeyv2.h>
5#import <netinet6/ipsec.h>
6#import <arpa/inet.h>
7#import <NetworkExtension/NetworkExtensionPrivate.h>
8#import <System/net/bpf.h>
9#import <System/netinet/ip.h>
10#import <System/netinet/ip6.h>
11
12#import <sys/mbuf.h>
13
14
15T_GLOBAL_META(
16	T_META_NAMESPACE("xnu.ipsec"),
17	T_META_ASROOT(true),
18	T_META_CHECK_LEAKS(false));
19
20typedef enum {
21	TEST_INVALID = 0,
22	TEST_IPSEC_IPv4_ENCAPSULATE_PANIC = 1,
23	TEST_IPSEC_IPv6_ENCAPSULATE_PANIC = 2,
24} test_identifier;
25
26#define TEST_SRC_ADDRESS_IPv4                           "10.0.0.2"
27#define TEST_DST_ADDRESS_IPv4                           "10.0.0.3"
28#define TEST_IPSEC_IPv4_INTERFACE_ADDRESS               "192.168.10.10"
29#define TEST_IPSEC_IPv6_INTERFACE_ADDRESS               "fdd3:0f89:9afd:9b9c::1234"
30#define TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS           "192.168.20.10"
31#define TEST_IPSEC_IPv4_INTERFACE_MASK                  "255.255.255.255"
32#define TEST_IPSEC_IPv6_INTERFACE_MASK                  "ffff:ffff:ffff:ffff::"
33
34static test_identifier test_id = TEST_INVALID;
35static dispatch_source_t pfkey_source = NULL;
36static NEVirtualInterfaceRef ipsecInterface = NULL;
37static NEVirtualInterfaceRef delegateIPsecInterface = NULL;
38static int bpf_fd = -1;
39
40static void bpf_write(int fd);
41static void pfkey_cleanup(void);
42static void pfkey_process_message_test_encapsulate_panic(uint8_t **mhp, int pfkey_socket);
43
44static void(*const process_pfkey_message_tests[])(uint8_t * *mhp, int pfkey_socket) =
45{
46	NULL,
47	pfkey_process_message_test_encapsulate_panic,    // TEST_IPSEC_IPv4_ENCAPSULATE_PANIC
48	pfkey_process_message_test_encapsulate_panic,    // TEST_IPSEC_IPv6_ENCAPSULATE_PANIC
49};
50
51static void
52send_pkey_add_sa(int pfkey_socket, uint32_t spi, const char *src, const char *dst, int family)
53{
54	uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
55	bzero(payload, sizeof(payload));
56	uint16_t tlen = 0;
57
58	struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
59	msg_payload->sadb_msg_version = PF_KEY_V2;
60	msg_payload->sadb_msg_type = SADB_ADD;
61	msg_payload->sadb_msg_errno = 0;
62	msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
63	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
64	msg_payload->sadb_msg_reserved = 0;
65	msg_payload->sadb_msg_seq = 0;
66	msg_payload->sadb_msg_pid = (u_int32_t)getpid();
67	tlen += sizeof(*msg_payload);
68
69	struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen);
70	sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload));
71	sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA;
72	sa2_payload->sa.sadb_sa_spi = htonl(spi);
73	sa2_payload->sa.sadb_sa_replay = 4;
74	sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL;
75	sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256;
76	sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC;
77	sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE);
78	sa2_payload->sadb_sa_natt_src_port = htons(4500);
79	sa2_payload->sadb_sa_natt_port = 4500;
80	sa2_payload->sadb_sa_natt_interval = 20;
81	sa2_payload->sadb_sa_natt_offload_interval = 0;
82	tlen += sizeof(*sa2_payload);
83
84	struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen);
85	sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload));
86	sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
87	sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TUNNEL;
88	sa2_x_payload->sadb_x_sa2_reqid = 0;
89	tlen += sizeof(*sa2_x_payload);
90
91	uint8_t prefixlen = (family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3);
92
93	struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
94	src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
95	src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
96	src_address_payload->sadb_address_prefixlen = prefixlen;
97	src_address_payload->sadb_address_reserved = 0;
98	tlen += sizeof(*src_address_payload);
99
100	if (family == AF_INET) {
101		struct sockaddr_in *src4 = (struct sockaddr_in *)(void *)(payload + tlen);
102		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, src, &src4->sin_addr), 1, "src address fail");
103		src4->sin_family = AF_INET;
104		src4->sin_len = sizeof(*src4);
105		uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src4->sin_len);
106		src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
107		tlen += PFKEY_ALIGN8(src4->sin_len);
108	} else {
109		struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
110		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, src, &src6->sin6_addr), 1, "src address fail");
111		src6->sin6_family = AF_INET6;
112		src6->sin6_len = sizeof(*src6);
113		uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src6->sin6_len);
114		src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
115		tlen += PFKEY_ALIGN8(src6->sin6_len);
116	}
117
118	struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
119	dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
120	dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
121	dst_address_payload->sadb_address_prefixlen = prefixlen;
122	dst_address_payload->sadb_address_reserved = 0;
123	tlen += sizeof(*dst_address_payload);
124
125	if (family == AF_INET) {
126		struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)(payload + tlen);
127		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, dst, &dst4->sin_addr), 1, "dst address fail");
128		dst4->sin_family = AF_INET;
129		dst4->sin_len = sizeof(*dst4);
130		uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst4->sin_len);
131		dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
132		tlen += PFKEY_ALIGN8(dst4->sin_len);
133	} else {
134		struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
135		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, dst, &dst6->sin6_addr), 1, "dst address fail");
136		dst6->sin6_family = AF_INET6;
137		dst6->sin6_len = sizeof(*dst6);
138		uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst6->sin6_len);
139		dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
140		tlen += PFKEY_ALIGN8(dst6->sin6_len);
141	}
142
143	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(ipsecInterface);
144	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
145	char ifname[IFNAMSIZ];
146	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
147
148	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
149	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get delegate ipsec interface name");
150	char delegateIfname[IFNAMSIZ];
151	CFStringGetCString(delegateIPsecIfName, delegateIfname, IFNAMSIZ, kCFStringEncodingUTF8);
152
153	struct sadb_x_ipsecif *ipsec_if_payload = (struct sadb_x_ipsecif *)(void *)(payload + tlen);
154	ipsec_if_payload->sadb_x_ipsecif_len = PFKEY_UNIT64(sizeof(*ipsec_if_payload));
155	ipsec_if_payload->sadb_x_ipsecif_exttype = SADB_X_EXT_IPSECIF;
156	strncpy(ipsec_if_payload->sadb_x_ipsecif_ipsec_if, ifname, strlen(ifname));
157	strncpy(ipsec_if_payload->sadb_x_ipsecif_outgoing_if, delegateIfname, strlen(delegateIfname));
158	tlen += sizeof(*ipsec_if_payload);
159
160	struct sadb_key *encrypt_key_payload = (struct sadb_key *)(void *)(payload + tlen);
161	uint16_t len = sizeof(*encrypt_key_payload) + PFKEY_ALIGN8(32);
162	encrypt_key_payload->sadb_key_len = PFKEY_UNIT64(len);
163	encrypt_key_payload->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
164	encrypt_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
165	encrypt_key_payload->sadb_key_reserved = 0;
166	tlen += sizeof(*encrypt_key_payload);
167	arc4random_buf(payload + tlen, 32);
168	tlen += PFKEY_ALIGN8(32);
169
170	struct sadb_key *auth_key_payload = (struct sadb_key *)(void *)(payload + tlen);
171	len = sizeof(*auth_key_payload) + PFKEY_ALIGN8(32);
172	auth_key_payload->sadb_key_len = PFKEY_UNIT64(len);
173	auth_key_payload->sadb_key_exttype = SADB_EXT_KEY_AUTH;
174	auth_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
175	auth_key_payload->sadb_key_reserved = 0;
176	tlen += sizeof(*auth_key_payload);
177	arc4random_buf(payload + tlen, 32);
178	tlen += PFKEY_ALIGN8(32);
179
180	struct sadb_lifetime *hard_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
181	hard_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*hard_lifetime_payload));
182	hard_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
183	tlen += sizeof(*hard_lifetime_payload);
184
185	struct sadb_lifetime *soft_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
186	soft_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*soft_lifetime_payload));
187	soft_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
188	tlen += sizeof(*soft_lifetime_payload);
189
190	// Update the total length
191	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
192	T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send update sa");
193}
194
195static void
196send_pfkey_flush_sa(int pfkey_socket)
197{
198	uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
199	bzero(payload, sizeof(payload));
200	uint16_t tlen = 0;
201
202	struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
203	msg_payload->sadb_msg_version = PF_KEY_V2;
204	msg_payload->sadb_msg_type = SADB_FLUSH;
205	msg_payload->sadb_msg_errno = 0;
206	msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
207	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
208	msg_payload->sadb_msg_reserved = 0;
209	msg_payload->sadb_msg_seq = 0;
210	msg_payload->sadb_msg_pid = (u_int32_t)getpid();
211	tlen += sizeof(*msg_payload);
212
213	// Update the total length
214	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
215	T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush sa");
216}
217
218static void
219pfkey_cleanup(void)
220{
221	if (pfkey_source != NULL) {
222		int pfkey_socket = (int)dispatch_source_get_handle(pfkey_source);
223		if (pfkey_socket > 0) {
224			send_pfkey_flush_sa(pfkey_socket);
225		}
226		dispatch_source_cancel(pfkey_source);
227		pfkey_source = NULL;
228	}
229}
230
231static void
232pfkey_align(struct sadb_msg *msg, uint8_t **mhp)
233{
234	struct sadb_ext *ext;
235	int i;
236	uint8_t *p;
237	uint8_t *ep;     /* XXX should be passed from upper layer */
238
239	/* validity check */
240	T_QUIET; T_ASSERT_NOTNULL(msg, "pfkey align msg");
241	T_QUIET; T_ASSERT_NOTNULL(mhp, "pfkey align mhp");
242
243	/* initialize */
244	for (i = 0; i < SADB_EXT_MAX + 1; i++) {
245		mhp[i] = NULL;
246	}
247
248	mhp[0] = (void *)msg;
249
250	/* initialize */
251	p = (void *) msg;
252	ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
253
254	/* skip base header */
255	p += sizeof(struct sadb_msg);
256
257	while (p < ep) {
258		ext = (void *)p;
259		T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + sizeof(*ext)), "pfkey extension header beyond end of buffer");
260		T_QUIET; T_ASSERT_GE_ULONG((unsigned long)PFKEY_EXTLEN(ext), sizeof(*ext), "pfkey extension shorter than extension header");
261		T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + PFKEY_EXTLEN(ext)), "pfkey extension length beyond end of buffer");
262
263		T_QUIET; T_EXPECT_NULL(mhp[ext->sadb_ext_type], "duplicate extension type %u payload", ext->sadb_ext_type);
264
265		/* set pointer */
266		switch (ext->sadb_ext_type) {
267		case SADB_EXT_SA:
268		case SADB_EXT_LIFETIME_CURRENT:
269		case SADB_EXT_LIFETIME_HARD:
270		case SADB_EXT_LIFETIME_SOFT:
271		case SADB_EXT_ADDRESS_SRC:
272		case SADB_EXT_ADDRESS_DST:
273		case SADB_EXT_ADDRESS_PROXY:
274		case SADB_EXT_KEY_AUTH:
275		/* XXX should to be check weak keys. */
276		case SADB_EXT_KEY_ENCRYPT:
277		/* XXX should to be check weak keys. */
278		case SADB_EXT_IDENTITY_SRC:
279		case SADB_EXT_IDENTITY_DST:
280		case SADB_EXT_SENSITIVITY:
281		case SADB_EXT_PROPOSAL:
282		case SADB_EXT_SUPPORTED_AUTH:
283		case SADB_EXT_SUPPORTED_ENCRYPT:
284		case SADB_EXT_SPIRANGE:
285		case SADB_X_EXT_POLICY:
286		case SADB_X_EXT_SA2:
287		case SADB_EXT_SESSION_ID:
288		case SADB_EXT_SASTAT:
289#ifdef SADB_X_EXT_NAT_T_TYPE
290		case SADB_X_EXT_NAT_T_TYPE:
291		case SADB_X_EXT_NAT_T_SPORT:
292		case SADB_X_EXT_NAT_T_DPORT:
293		case SADB_X_EXT_NAT_T_OA:
294#endif
295#ifdef SADB_X_EXT_TAG
296		case SADB_X_EXT_TAG:
297#endif
298#ifdef SADB_X_EXT_PACKET
299		case SADB_X_EXT_PACKET:
300#endif
301		case SADB_X_EXT_IPSECIF:
302		case SADB_X_EXT_ADDR_RANGE_SRC_START:
303		case SADB_X_EXT_ADDR_RANGE_SRC_END:
304		case SADB_X_EXT_ADDR_RANGE_DST_START:
305		case SADB_X_EXT_ADDR_RANGE_DST_END:
306#ifdef SADB_MIGRATE
307		case SADB_EXT_MIGRATE_ADDRESS_SRC:
308		case SADB_EXT_MIGRATE_ADDRESS_DST:
309		case SADB_X_EXT_MIGRATE_IPSECIF:
310#endif
311			mhp[ext->sadb_ext_type] = (void *)ext;
312			break;
313		default:
314			T_FAIL("bad extension type %u", ext->sadb_ext_type);
315			T_END;
316		}
317
318		p += PFKEY_EXTLEN(ext);
319	}
320
321	T_QUIET; T_EXPECT_EQ_PTR((void *)ep, (void *)p, "invalid pfkey message length");
322	return;
323}
324
325static void
326pfkey_process_message_test_encapsulate_panic(uint8_t **mhp, __unused int pfkey_socket)
327{
328	struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
329	static uint32_t spi = 0;
330	static uint8_t added_sa_counter = 0;
331
332	if (message->sadb_msg_pid != (uint32_t)getpid()) {
333		return;
334	}
335
336	if (message->sadb_msg_errno != 0) {
337		T_FAIL("SADB add SA received error %d", message->sadb_msg_errno);
338		T_END;
339	}
340
341	switch (message->sadb_msg_type) {
342	case SADB_ADD:
343	{
344		struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
345		T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
346		spi = ntohl(sa_message->sadb_sa_spi);
347		T_LOG("added sa 0x%x", spi);
348		added_sa_counter++;
349		if (added_sa_counter == 2) {
350			bpf_write(bpf_fd);
351		}
352		break;
353	}
354	case SADB_FLUSH:
355	case SADB_X_SPDFLUSH:
356		break;
357	default:
358		T_FAIL("bad SADB message type %u", message->sadb_msg_type);
359		T_END;
360	}
361	return;
362}
363
364static void
365recv_pfkey_message(int pfkey_socket)
366{
367	uint8_t buffer[8192] __attribute__((aligned(4)));
368	struct iovec iovecs[1] = {
369		{ buffer, sizeof(buffer) },
370	};
371	struct msghdr msg = {
372		NULL,
373		0,
374		iovecs,
375		sizeof(iovecs) / sizeof(iovecs[0]),
376		NULL,
377		0,
378		0,
379	};
380
381	do {
382		ssize_t result = -1;
383		memset(buffer, 0, sizeof(buffer));
384		T_QUIET; T_ASSERT_POSIX_SUCCESS(result = recvmsg(pfkey_socket, &msg, 0), NULL);
385
386		if (result > 0) {
387			T_QUIET; T_ASSERT_GE_ULONG((size_t)result, sizeof(struct sadb_msg), "Invalid PFKey message size: %zu", result);
388			struct sadb_msg *hdr = (struct sadb_msg *)buffer;
389			uint8_t *mhp[SADB_EXT_MAX + 1];
390			pfkey_align(hdr, mhp);
391			(*process_pfkey_message_tests[test_id])(mhp, pfkey_socket);
392		} else if (result == 0) {
393			T_LOG("PFKey socket received EOF");
394			break;
395		}
396	} while (1);
397}
398
399static int
400pfkey_setup_socket(void)
401{
402	int pfkey_socket = -1;
403
404	T_QUIET; T_ASSERT_POSIX_SUCCESS(pfkey_socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL);
405
406	struct mbstat mbstat;
407	size_t len_mbstat = sizeof(struct mbstat);
408
409	T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.ipc.mbstat", &mbstat, &len_mbstat, NULL, 0), "kern.ipc.mbstat");
410
411	int bufsiz = 0;
412	const unsigned long newbufk = 1536;
413	unsigned long oldmax;
414	size_t  oldmaxsize = sizeof(oldmax);
415	unsigned long newmax = newbufk * (1024 + mbstat.m_msize / 2);
416
417	if (sysctlbyname("kern.ipc.maxsockbuf", &oldmax, &oldmaxsize, &newmax, sizeof(newmax)) != 0) {
418		bufsiz = 233016;        /* Max allowed by default */
419	} else {
420		bufsiz = newbufk * 1024;
421	}
422
423	T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)), "pfkey set snd socket buf failed %d", bufsiz);
424	T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)), "pfkey set recv socket buf failed %d", bufsiz);
425
426	pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)pfkey_socket, 0, dispatch_get_main_queue());
427	T_QUIET; T_ASSERT_NOTNULL(pfkey_source, "dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ...)");
428	dispatch_source_set_event_handler(pfkey_source, ^{
429		recv_pfkey_message(pfkey_socket);
430	});
431	dispatch_source_set_cancel_handler(pfkey_source, ^{
432		close(pfkey_socket);
433	});
434	dispatch_resume(pfkey_source);
435	return pfkey_socket;
436}
437
438static int
439bpf_new(void)
440{
441	char bpfdev[256];
442	int i;
443	int fd = -1;
444
445	for (i = 0; true; i++) {
446		snprintf(bpfdev, sizeof(bpfdev), "/dev/bpf%d", i);
447		fd = open(bpfdev, O_RDWR, 0);
448		if (fd >= 0) {
449			break;
450		}
451		if (errno != EBUSY) {
452			break;
453		}
454	}
455	return fd;
456}
457
458static int
459bpf_setif(int fd, const char *en_name)
460{
461	struct ifreq ifr;
462
463	strlcpy(ifr.ifr_name, en_name, sizeof(ifr.ifr_name));
464	return ioctl(fd, BIOCSETIF, &ifr);
465}
466
467static int
468bpf_sethdr_complete(int fd)
469{
470	u_int8_t hdr_complete = 1;
471	return ioctl(fd, BIOCSHDRCMPLT, &hdr_complete);
472}
473
474static void
475bpf_write(int fd)
476{
477	if (test_id == TEST_IPSEC_IPv4_ENCAPSULATE_PANIC) {
478		char buffer[500];
479		struct ip *ipheader = (void *)buffer;
480		ipheader->ip_v = IPVERSION;
481		ipheader->ip_hl = (sizeof(struct ip) - 4) >> 2;
482		ipheader->ip_ttl = MAXTTL;
483		ipheader->ip_p = IPPROTO_UDP;
484		T_QUIET; T_ASSERT_POSIX_SUCCESS(write(fd, buffer, 500), "bpf write call failed");
485		T_PASS("wrote bad ip header successfully");
486		T_END;
487	} else if (test_id == TEST_IPSEC_IPv6_ENCAPSULATE_PANIC) {
488		struct ip6_hdr ip6 = {0};
489		ip6.ip6_vfc |= IPV6_VERSION;
490		T_QUIET; T_ASSERT_POSIX_SUCCESS(write(fd, &ip6, sizeof(ip6) - 4), "bpf write call failed");
491		T_PASS("wrote bad ipv6 header successfully");
492		T_END;
493	}
494}
495
496static void
497bpf_socket_setup(void)
498{
499	int status = -1;
500
501	bpf_fd = bpf_new();
502	T_QUIET; T_ASSERT_NE(bpf_fd, -1, "failed to create bpf file descriptor");
503
504	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(ipsecInterface);
505	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
506
507	char ifname[IFNAMSIZ];
508	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
509
510	status = bpf_setif(bpf_fd, ifname);
511	T_QUIET; T_ASSERT_NE(status, -1, "failed to set bpf interface");
512
513	status = bpf_sethdr_complete(bpf_fd);
514	T_QUIET; T_ASSERT_NE(status, -1, "failed to set bpf header complete");
515}
516
517static NEVirtualInterfaceRef
518ipsec_interface_setup(CFStringRef interfaceAddress, CFStringRef interfaceMask)
519{
520	Boolean status = FALSE;
521
522	NEVirtualInterfaceRef interface = NEVirtualInterfaceCreate(NULL, kNEVirtualInterfaceValTypeIPSec, dispatch_get_main_queue(), NULL);
523	T_QUIET; T_ASSERT_NOTNULL(interface, "ipsec interface creation failed");
524	status = NEVirtualInterfaceSetMTU(interface, 1400);
525	if (status == FALSE) {
526		T_FAIL("Failed to set MTU on ipsec interface");
527		T_END;
528	}
529
530	status = NEVirtualInterfaceAddAddress(interface, interfaceAddress, interfaceMask);
531	if (status == FALSE) {
532		T_FAIL("Failed to set address on ipsec interface");
533		T_END;
534	}
535
536	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(interface);
537	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
538
539	char ifname[IFNAMSIZ];
540	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
541
542	T_LOG("%s interface setup", ifname);
543	return interface;
544}
545
546static void
547ipsec_interface_set_delegate(NEVirtualInterfaceRef interface, CFStringRef delegateInterfaceName)
548{
549	Boolean status = NEVirtualInterfaceSetDelegateInterface(interface, delegateInterfaceName);
550	if (status == FALSE) {
551		T_FAIL("Failed to set delegate on ipsec interface");
552		T_END;
553	}
554
555	return;
556}
557
558static void
559ipsec_cleanup(void)
560{
561	pfkey_cleanup();
562
563	if (ipsecInterface != NULL) {
564		NEVirtualInterfaceInvalidate(ipsecInterface);
565		ipsecInterface = NULL;
566	}
567
568	if (delegateIPsecInterface != NULL) {
569		NEVirtualInterfaceInvalidate(delegateIPsecInterface);
570		delegateIPsecInterface = NULL;
571	}
572
573	if (bpf_fd != -1) {
574		close(bpf_fd);
575		bpf_fd = -1;
576	}
577}
578
579T_DECL(ipsec_ipv4_encapsulate_panic_63139357, "ipsec: outer ip header length less than 20")
580{
581	test_id = TEST_IPSEC_IPv4_ENCAPSULATE_PANIC;
582
583	T_ATEND(ipsec_cleanup);
584
585	ipsecInterface = ipsec_interface_setup(CFSTR(TEST_IPSEC_IPv4_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
586	delegateIPsecInterface = ipsec_interface_setup(CFSTR(TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
587
588	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
589	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get ipsec interface name");
590	ipsec_interface_set_delegate(ipsecInterface, delegateIPsecIfName);
591
592	bpf_socket_setup();
593
594	int pfkey_socket = pfkey_setup_socket();
595	send_pfkey_flush_sa(pfkey_socket);
596
597	send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
598	send_pkey_add_sa(pfkey_socket, 0x23456789, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
599
600	dispatch_main();
601}
602
603T_DECL(ipsec_ipv6_encapsulate_panic_63139357, "ipsec: payload less than IPv6 header")
604{
605	test_id = TEST_IPSEC_IPv6_ENCAPSULATE_PANIC;
606
607	T_ATEND(ipsec_cleanup);
608
609	ipsecInterface = ipsec_interface_setup(CFSTR(TEST_IPSEC_IPv6_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv6_INTERFACE_MASK));
610	delegateIPsecInterface = ipsec_interface_setup(CFSTR(TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
611
612	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
613	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get ipsec interface name");
614	ipsec_interface_set_delegate(ipsecInterface, delegateIPsecIfName);
615
616	bpf_socket_setup();
617
618	int pfkey_socket = pfkey_setup_socket();
619	send_pfkey_flush_sa(pfkey_socket);
620
621	send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
622	send_pkey_add_sa(pfkey_socket, 0x23456789, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
623
624	dispatch_main();
625}
626