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