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