this repo has no description
at fixPythonPipStalling 535 lines 14 kB view raw
1/* 2 * Copyright (c) 2006, 2008, 2009, 2011-2019 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * SCNetworkSignature.c 26 * - implementation of SCNetworkSignatureRef API that allows access to 27 network identification information 28 * 29 */ 30/* 31 * Modification History 32 * 33 * November 6, 2006 Dieter Siegmund (dieter@apple.com) 34 * - initial revision 35 */ 36 37 38#include <netinet/in.h> 39#include <CoreFoundation/CFDictionary.h> 40#include <CoreFoundation/CFString.h> 41#include <CoreFoundation/CFArray.h> 42#include <CoreFoundation/CFRuntime.h> 43#include <SystemConfiguration/SCDynamicStore.h> 44#include <SystemConfiguration/SCValidation.h> 45#include <SystemConfiguration/SCPrivate.h> 46#include "SCNetworkSignature.h" 47#include "SCNetworkSignaturePrivate.h" 48#include <arpa/inet.h> 49#include <sys/types.h> 50#include <sys/socket.h> 51#include <net/if.h> 52#include <nw/private.h> 53 54#pragma mark SCNetworkSignature Supporting APIs 55 56static CFStringRef 57create_global_state_v4_key(void) 58{ 59 return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, 60 kSCDynamicStoreDomainState, 61 kSCEntNetIPv4); 62 63} 64 65static CFStringRef 66create_global_setup_v4_key(void) 67{ 68 return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, 69 kSCDynamicStoreDomainSetup, 70 kSCEntNetIPv4); 71} 72 73static CFStringRef 74create_ipv4_services_pattern(void) 75{ 76 return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 77 kSCDynamicStoreDomainState, 78 kSCCompAnyRegex, 79 kSCEntNetIPv4); 80} 81 82static CFStringRef 83create_ipv6_services_pattern(void) 84{ 85 return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 86 kSCDynamicStoreDomainState, 87 kSCCompAnyRegex, 88 kSCEntNetIPv6); 89} 90 91static CFDictionaryRef 92copy_services_for_address_family(CFAllocatorRef alloc, int af) 93{ 94#pragma unused(alloc) 95 CFDictionaryRef info; 96 CFArrayRef patterns; 97 CFStringRef pattern; 98 CFStringRef prop; 99 100 prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6; 101 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 102 kSCDynamicStoreDomainState, 103 kSCCompAnyRegex, 104 prop); 105 patterns = CFArrayCreate(NULL, 106 (const void * *)&pattern, 1, 107 &kCFTypeArrayCallBacks); 108 CFRelease(pattern); 109 info = SCDynamicStoreCopyMultiple(NULL, NULL, patterns); 110 CFRelease(patterns); 111 112 return (info); 113} 114 115 116static CF_RETURNS_RETAINED CFStringRef 117my_IPAddressToCFString(int af, const void * src_p) 118{ 119 char ntopbuf[INET6_ADDRSTRLEN]; 120 121 if (inet_ntop(af, src_p, ntopbuf, sizeof(ntopbuf)) != NULL) { 122 return (CFStringCreateWithCString(NULL, ntopbuf, 123 kCFStringEncodingASCII)); 124 } 125 return (NULL); 126} 127 128#pragma mark - 129 130 131#pragma mark SCNetworkSignature APIs 132 133CFStringRef 134SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc, 135 const struct sockaddr * addr) 136{ 137#pragma unused(alloc) 138 CFStringRef ident = NULL; 139 CFDictionaryRef info = NULL; 140 CFStringRef global_state_v4_key = NULL; 141 CFDictionaryRef global_v4_state_dict = NULL; 142 CFArrayRef keys = NULL; 143 CFArrayRef patterns = NULL; 144 in_addr_t s_addr; 145 CFStringRef service = NULL; 146 CFDictionaryRef service_dict = NULL; 147 CFStringRef service_id = NULL; 148 struct sockaddr_in * sin_p; 149 CFStringRef v4_service_pattern = NULL; 150 151 /* only accept 0.0.0.0 (i.e. default) for now */ 152 if (addr == NULL 153 || addr->sa_family != AF_INET 154 || addr->sa_len != sizeof(struct sockaddr_in)) { 155 _SCErrorSet(kSCStatusInvalidArgument); 156 goto done; 157 } 158 159 /* ALIGN: force alignment */ 160 sin_p = (struct sockaddr_in *)(void *)addr; 161 memcpy(&s_addr, &sin_p->sin_addr.s_addr, sizeof(s_addr)); 162 if (s_addr != 0) { 163 _SCErrorSet(kSCStatusInvalidArgument); 164 goto done; 165 } 166 167 global_state_v4_key = create_global_state_v4_key(); 168 keys = CFArrayCreate(NULL, (const void * *)&global_state_v4_key, 169 1, &kCFTypeArrayCallBacks); 170 171 v4_service_pattern = create_ipv4_services_pattern(); 172 patterns = CFArrayCreate(NULL, (const void * *)&v4_service_pattern, 1, 173 &kCFTypeArrayCallBacks); 174 175 info = SCDynamicStoreCopyMultiple(NULL, keys, patterns); 176 177 if (info == NULL 178 || CFDictionaryGetCount(info) == 0) { 179 goto done; 180 } 181 182 global_v4_state_dict = CFDictionaryGetValue(info, global_state_v4_key); 183 184 if (isA_CFDictionary(global_v4_state_dict) == NULL) { 185 goto done; 186 } 187 188 service_id = CFDictionaryGetValue(global_v4_state_dict, 189 kSCDynamicStorePropNetPrimaryService); 190 191 if (isA_CFString(service_id) == NULL) { 192 goto done; 193 } 194 195 service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 196 kSCDynamicStoreDomainState, 197 service_id, kSCEntNetIPv4); 198 199 service_dict = CFDictionaryGetValue(info, service); 200 201 202 if (isA_CFDictionary(service_dict) == NULL 203 || CFDictionaryGetCount(service_dict) == 0) { 204 goto done; 205 } 206 207 ident = CFDictionaryGetValue(service_dict, kStoreKeyNetworkSignature); 208 ident = isA_CFString(ident); 209done: 210 if (ident != NULL) { 211 CFRetain(ident); 212 } else { 213 _SCErrorSet(kSCStatusFailed); 214 } 215 if (info != NULL) { 216 CFRelease(info); 217 } 218 if (global_state_v4_key != NULL) { 219 CFRelease(global_state_v4_key); 220 } 221 if (service != NULL) { 222 CFRelease(service); 223 } 224 if (keys != NULL) { 225 CFRelease(keys); 226 } 227 if (patterns != NULL) { 228 CFRelease(patterns); 229 } 230 if (v4_service_pattern != NULL) { 231 CFRelease(v4_service_pattern); 232 } 233 return (ident); 234} 235 236CFArrayRef /* of CFStringRef's */ 237SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc) 238{ 239#pragma unused(alloc) 240 CFMutableArrayRef active = NULL; 241 CFIndex count = 0; 242 CFStringRef global_setup_v4_key = NULL; 243 CFDictionaryRef global_v4_dict; 244 int i; 245 CFDictionaryRef info = NULL; 246 CFArrayRef keys = NULL; 247 CFMutableArrayRef patterns = NULL; 248 CFRange range; 249 CFMutableDictionaryRef services_dict = NULL; 250 CFArrayRef service_order; 251 CFStringRef v4_service_pattern = NULL; 252 CFStringRef v6_service_pattern = NULL; 253 const void * * values = NULL; 254#define KEYS_STATIC_COUNT 10 255 const void * values_static[KEYS_STATIC_COUNT]; 256 257 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 258 259 global_setup_v4_key = create_global_setup_v4_key(); 260 keys = CFArrayCreate(NULL, (const void * *)&global_setup_v4_key, 1, 261 &kCFTypeArrayCallBacks); 262 263 v4_service_pattern = create_ipv4_services_pattern(); 264 CFArrayAppendValue(patterns, v4_service_pattern); 265 266 v6_service_pattern = create_ipv6_services_pattern(); 267 CFArrayAppendValue(patterns, v6_service_pattern); 268 269 info = SCDynamicStoreCopyMultiple(NULL, keys, patterns); 270 271 if (info == NULL 272 || CFDictionaryGetCount(info) == 0) { 273 goto done; 274 } 275 276 services_dict = CFDictionaryCreateMutableCopy(NULL, 0, info); 277 /* 278 * The service_dict should only contain services and once each 279 * service has been visited, it will be removed from the dictionary. 280 */ 281 CFDictionaryRemoveValue(services_dict, global_setup_v4_key); 282 283 global_v4_dict = CFDictionaryGetValue(info, global_setup_v4_key); 284 285 if (isA_CFDictionary(global_v4_dict) != NULL) { 286 service_order = CFDictionaryGetValue(global_v4_dict, 287 kSCPropNetServiceOrder); 288 if (isA_CFArray(service_order) != NULL) { 289 count = CFArrayGetCount(service_order); 290 } 291 } 292 293 active = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 294 295 range = CFRangeMake(0, 0); 296 297 for (i = 0; i < count ; i++) { 298 int j; 299 CFStringRef network_sig; 300 CFStringRef service; 301 CFStringRef service_id; 302 CFDictionaryRef service_info; 303 CFStringRef afs[2] = {kSCEntNetIPv4, kSCEntNetIPv6}; 304 305 service_id = CFArrayGetValueAtIndex(service_order, i); 306 307 if (isA_CFString(service_id) == NULL) { 308 continue; 309 } 310 311 for (j = 0; j < 2; j++) { 312 service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 313 kSCDynamicStoreDomainState, 314 service_id, afs[j]); 315 316 service_info = CFDictionaryGetValue(services_dict, service); 317 318 /* Does this service have a signature? */ 319 if (isA_CFDictionary(service_info) != NULL) { 320 network_sig = CFDictionaryGetValue(service_info, kStoreKeyNetworkSignature); 321 if (isA_CFString(network_sig) && !CFArrayContainsValue(active, range, network_sig)) { 322 CFArrayAppendValue(active, network_sig); 323 network_sig = NULL; 324 range.length++; 325 } 326 CFDictionaryRemoveValue(services_dict, service); 327 } 328 CFRelease(service); 329 } 330 } 331 332 count = CFDictionaryGetCount(services_dict); 333 if (count != 0) { 334 if (count > KEYS_STATIC_COUNT) { 335 values = (const void * *)malloc(sizeof(*values) * count); 336 } else { 337 values = values_static; 338 } 339 CFDictionaryGetKeysAndValues(services_dict, NULL, 340 (const void * *)values); 341 } 342 343 for (i = 0; i < count; i++) { 344 CFStringRef network_sig; 345 CFDictionaryRef service_dict = (CFDictionaryRef)values[i]; 346 347 if (isA_CFDictionary(service_dict) == NULL) { 348 continue; 349 } 350 351 network_sig = CFDictionaryGetValue(service_dict, 352 kStoreKeyNetworkSignature); 353 /* Does this service have a signature? */ 354 if (isA_CFString(network_sig) && !CFArrayContainsValue(active, range, network_sig)) { 355 CFArrayAppendValue(active, network_sig); 356 range.length++; 357 network_sig = NULL; 358 } 359 } 360 done: 361 if (info != NULL) { 362 CFRelease(info); 363 } 364 if (services_dict != NULL) { 365 CFRelease(services_dict); 366 } 367 if (global_setup_v4_key != NULL) { 368 CFRelease(global_setup_v4_key); 369 } 370 if (v4_service_pattern != NULL) { 371 CFRelease(v4_service_pattern); 372 } 373 if (v6_service_pattern != NULL) { 374 CFRelease(v6_service_pattern); 375 } 376 if (values != NULL && values != values_static) { 377 free(values); 378 } 379 if (keys != NULL) { 380 CFRelease(keys); 381 } 382 if (patterns != NULL) { 383 CFRelease(patterns); 384 } 385 if (active != NULL && CFArrayGetCount(active) == 0) { 386 CFRelease(active); 387 active = NULL; 388 } 389 if (active == NULL) { 390 _SCErrorSet(kSCStatusFailed); 391 } 392 return (active); 393} 394 395 396CFStringRef 397SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc, 398 int sock_fd) 399{ 400 CFStringRef addresses_key; 401 int af; 402 CFIndex count; 403 int i; 404 char if_name[IFNAMSIZ]; 405 CFStringRef if_name_cf = NULL; 406 conninfo_t * info = NULL; 407 const void * * keys = NULL; 408#define KEYS_STATIC_COUNT 10 409 const void * keys_static[KEYS_STATIC_COUNT]; 410 const void * local_ip_p; 411 CFStringRef local_ip_str = NULL; 412 CFStringRef ret_signature = NULL; 413 CFDictionaryRef service_info = NULL; 414 int status = kSCStatusFailed; 415 416 if (copyconninfo(sock_fd, SAE_CONNID_ANY, &info) != 0) { 417 status = kSCStatusInvalidArgument; 418 goto done; 419 } 420 if ((info->ci_flags & CIF_CONNECTED) == 0 421 || info->ci_src == NULL) { 422 goto done; 423 } 424 af = info->ci_src->sa_family; 425 switch (af) { 426 case AF_INET: 427 addresses_key = kSCPropNetIPv4Addresses; 428 local_ip_p = &((struct sockaddr_in *) 429 (void *)info->ci_src)->sin_addr; 430 break; 431 case AF_INET6: 432 addresses_key = kSCPropNetIPv6Addresses; 433 local_ip_p = &((struct sockaddr_in6 *) 434 (void *)info->ci_src)->sin6_addr; 435 break; 436 default: 437 status = kSCStatusInvalidArgument; 438 goto done; 439 } 440 441 /* search for service with matching IP address and interface name */ 442 service_info = copy_services_for_address_family(alloc, af); 443 if (service_info == NULL) { 444 goto done; 445 } 446 local_ip_str = my_IPAddressToCFString(af, local_ip_p); 447 if (local_ip_str == NULL) { 448 goto done; 449 } 450 if (info->ci_ifindex != 0 451 && if_indextoname(info->ci_ifindex, if_name) != NULL) { 452 if_name_cf 453 = CFStringCreateWithCString(NULL, if_name, 454 kCFStringEncodingASCII); 455 } 456 count = CFDictionaryGetCount(service_info); 457 if (count > KEYS_STATIC_COUNT) { 458 keys = (const void * *)malloc(sizeof(*keys) * count); 459 } 460 else { 461 keys = keys_static; 462 } 463 CFDictionaryGetKeysAndValues(service_info, keys, NULL); 464 for (i = 0; i < count; i++) { 465 CFArrayRef addrs; 466 CFRange range; 467 CFStringRef signature; 468 CFDictionaryRef value; 469 470 value = CFDictionaryGetValue(service_info, keys[i]); 471 if (isA_CFDictionary(value) == NULL) { 472 continue; 473 } 474 signature = CFDictionaryGetValue(value, 475 kStoreKeyNetworkSignature); 476 if (isA_CFString(signature) == NULL) { 477 /* no signature */ 478 continue; 479 } 480 if (if_name_cf != NULL) { 481 CFStringRef confirmed_if; 482 CFStringRef this_if; 483 484 this_if = CFDictionaryGetValue(value, 485 kSCPropInterfaceName); 486 if (isA_CFString(this_if) == NULL 487 || !CFEqual(this_if, if_name_cf)) { 488 /* no interface or it doesn't match */ 489 continue; 490 } 491 confirmed_if 492 = CFDictionaryGetValue(value, 493 kSCPropConfirmedInterfaceName); 494 if (isA_CFString(confirmed_if) != NULL 495 && !CFEqual(confirmed_if, if_name_cf)) { 496 /* confirmed interface doesn't match */ 497 continue; 498 } 499 } 500 501 addrs = CFDictionaryGetValue(value, addresses_key); 502 if (isA_CFArray(addrs) == NULL) { 503 continue; 504 } 505 range = CFRangeMake(0, CFArrayGetCount(addrs)); 506 if (CFArrayContainsValue(addrs, range, local_ip_str)) { 507 ret_signature = CFRetain(signature); 508 status = kSCStatusOK; 509 break; 510 } 511 } 512 513 done: 514 if (info != NULL) { 515 freeconninfo(info); 516 } 517 if (if_name_cf != NULL) { 518 CFRelease(if_name_cf); 519 } 520 if (local_ip_str != NULL) { 521 CFRelease(local_ip_str); 522 } 523 if (keys != NULL && keys != keys_static) { 524 free(keys); 525 } 526 if (service_info != NULL) { 527 CFRelease(service_info); 528 } 529 if (status != kSCStatusOK) { 530 _SCErrorSet(status); 531 } 532 return (ret_signature); 533} 534 535#pragma mark -