From 890c292f843a53dd09de01bd68c5f488675a307c Mon Sep 17 00:00:00 2001 From: Apple Date: Wed, 18 Jan 2017 19:11:50 +0000 Subject: [PATCH] Libinfo-503.50.4.tar.gz --- Libinfo.xcodeproj/project.pbxproj | 2 + lookup.subproj/si_getaddrinfo.c | 131 ++++++++++++++++++++++++++++++++++++ membership.subproj/membership.c | 137 +++++++++++++++++++++++++++++++------- 3 files changed, 247 insertions(+), 23 deletions(-) diff --git a/Libinfo.xcodeproj/project.pbxproj b/Libinfo.xcodeproj/project.pbxproj index 0cd0e5e..c318989 100644 --- a/Libinfo.xcodeproj/project.pbxproj +++ b/Libinfo.xcodeproj/project.pbxproj @@ -836,6 +836,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; OTHER_CFLAGS = ""; VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = "-Wno-error=deprecated-declarations"; WARNING_LDFLAGS = "-Wall"; }; name = Release; @@ -870,6 +871,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; OTHER_CFLAGS = "-DDEBUG=1"; VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = "-Wno-error=deprecated-declarations"; WARNING_LDFLAGS = "-Wall"; }; name = Debug; diff --git a/lookup.subproj/si_getaddrinfo.c b/lookup.subproj/si_getaddrinfo.c index 27ab2c8..6feaa51 100644 --- a/lookup.subproj/si_getaddrinfo.c +++ b/lookup.subproj/si_getaddrinfo.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1156,9 +1157,129 @@ _gai_nat64_synthesis(si_mod_t *si, const char *node, const void *servptr, int nu return _gai_sort_list(out_list, flags); } +static si_list_t * +_gai_nat64_second_pass(si_list_t *out, si_mod_t *si, const char *serv, uint32_t family, uint32_t socktype, + uint32_t proto, uint32_t flags, const char *interface) +{ + if (out == NULL || out->count == 0) + { + return NULL; + } + + /* validate AI_NUMERICHOST */ + if ((flags & AI_NUMERICHOST) != 0) + { + return NULL; + } + + /* validate family */ + if ((AF_UNSPEC != family) && (AF_INET6 != family)) + { + return NULL; + } + + /* skip if we already have an IPv6 address (unless it is v4-mapped) */ + for (uint32_t i = 0; i < out->count; i++) + { + si_addrinfo_t *a = (si_addrinfo_t *)((uintptr_t)out->entry[i] + sizeof(si_item_t)); + if (a->ai_family == AF_INET6) + { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)a->ai_addr.x; + if (!IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) + { + return NULL; + } + } + } + + si_list_t *out_list = NULL; + const uint32_t flags2 = flags & (~(AI_V4MAPPED | AI_V4MAPPED_CFG)); + + for (uint32_t i = 0; i < out->count; i++) + { + si_addrinfo_t *a = (si_addrinfo_t *)((uintptr_t)out->entry[i] + sizeof(si_item_t)); + struct in_addr *addr4 = NULL; + if (a->ai_family == AF_INET) + { + addr4 = &((struct sockaddr_in *)a->ai_addr.x)->sin_addr; + } + else if (a->ai_family == AF_INET6) + { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)a->ai_addr.x; + addr4 = (struct in_addr *)&(s6->sin6_addr.__u6_addr.__u6_addr32[3]); + } + else + { + continue; + } + + /* validate that IPv4 address is eligible for NAT64 synthesis */ +#if defined(NW_NAT64_API_VERSION) && NW_NAT64_API_VERSION >= 2 + if (!nw_nat64_can_v4_address_be_synthesized(addr4)) + { + continue; + } +#endif // NW_NAT64_API_VERSION + + char v4_str[INET_ADDRSTRLEN] = {0}; + if (NULL == inet_ntop(AF_INET, addr4, v4_str, sizeof(v4_str))) + { + continue; + } + + /* skip if we have a path (route) to this address as it might go through a VPN */ + nw_endpoint_t endpoint = nw_endpoint_create_address((struct sockaddr *)a->ai_addr.x); + if (endpoint == NULL) + { + continue; + } + nw_path_evaluator_t evaluator = nw_path_create_evaluator_for_endpoint(endpoint, NULL); + network_release(endpoint); + if (evaluator == NULL) + { + continue; + } + nw_path_t path = nw_path_evaluator_copy_path(evaluator); + network_release(evaluator); + if (path == NULL) + { + continue; + } + const nw_path_status_t status = nw_path_get_status(path); + network_release(path); + if (status != nw_path_status_unsatisfied) + { + continue; + } + + uint32_t err = SI_STATUS_NO_ERROR; + si_list_t *temp_list = si_addrinfo(si, v4_str, serv, AF_INET6, socktype, proto, flags2, interface, &err); + if (NULL == temp_list) + { + continue; + } + if (err != SI_STATUS_NO_ERROR) + { + si_list_release(temp_list); + continue; + } + if (NULL != out_list) + { + out_list = si_list_concat(out_list, temp_list); + si_list_release(temp_list); + } + else + { + out_list = temp_list; + } + } + return out_list; +} + si_list_t * si_addrinfo(si_mod_t *si, const char *node, const char *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface, uint32_t *err) { + const uint32_t family_ori = family, flags_ori = flags; int numerichost, numericserv = 0; int scope = 0; const void *nodeptr = NULL, *servptr = NULL; @@ -1360,6 +1481,16 @@ si_addrinfo(si_mod_t *si, const char *node, const char *serv, uint32_t family, u { /* or let the current module handle the host lookups intelligently */ out = si->vtable->sim_addrinfo(si, nodeptr, servptr, family, socktype, proto, flags, interface, err); + + /* run a second NAT64 pass in case a hostname was resolved over VPN to an IPv4 address + and it needs to be synthesized in order to be used on IPv6-only cellular */ + si_list_t *nat64_list2 = _gai_nat64_second_pass(out, si, serv, family_ori, socktype, + proto, flags_ori, interface); + if (nat64_list2 != NULL) + { + out = si_list_concat(out, nat64_list2); + } + return _gai_sort_list(out, flags); } diff --git a/membership.subproj/membership.c b/membership.subproj/membership.c index ff37c3c..6f4b6cf 100644 --- a/membership.subproj/membership.c +++ b/membership.subproj/membership.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "membership.h" #include "membershipPriv.h" @@ -142,6 +143,76 @@ _mbr_od_available(void) return false; } +static bool +parse_compatibility_uuid(const uuid_t uu, id_t *result, int *rec_type) +{ + id_t tempID; + + if (memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN) == 0) { + memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID)); + (*result) = ntohl(tempID); + if (rec_type != NULL) { + (*rec_type) = MBR_REC_TYPE_USER; + } + return true; + } else if (memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN) == 0) { + memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID)); + (*result) = ntohl(tempID); + if (rec_type != NULL) { + (*rec_type) = MBR_REC_TYPE_GROUP; + } + return true; + } + return false; +} + +static bool +compatibility_name_for_id(id_t id, int rec_type, char **result) +{ + int bufsize; + + if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) + return false; + + if (rec_type == MBR_REC_TYPE_USER) { + char buffer[bufsize]; + struct passwd pwd, *pwdp = NULL; + + if (getpwuid_r(id, &pwd, buffer, bufsize, &pwdp) != 0 || pwdp == NULL) { + return false; + } + (*result) = strdup(pwd.pw_name); + return (*result) != NULL; + } else if (rec_type == MBR_REC_TYPE_GROUP) { + char buffer[bufsize]; + struct group grp, *grpp = NULL; + + if (getgrgid_r(id, &grp, buffer, bufsize, &grpp) != 0 || grpp == NULL) { + return false; + } + (*result) = strdup(grp.gr_name); + return (*result) != NULL; + } + return false; +} + +static bool +compatibility_name_for_uuid(const uuid_t uu, char **result, int *rec_type) +{ + int temp_type; + id_t id; + + if (parse_compatibility_uuid(uu, &id, &temp_type) && + compatibility_name_for_id(id, temp_type, result)) { + if (rec_type != NULL) { + (*rec_type) = temp_type; + } + return true; + } else { + return false; + } +} + int mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_size, int target_type, void **result, int *rec_type) { @@ -178,31 +249,17 @@ mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_ case ID_TYPE_GID: case ID_TYPE_UID: case ID_TYPE_UID_OR_GID: - /* shortcut UUIDs using compatibilty prefixes */ + /* shortcut UUIDs using compatibility prefixes */ if (id_type == ID_TYPE_UUID) { - const uint8_t *uu = identifier; - + id_t *tempRes; + if (identifier_size != sizeof(uuid_t)) return EINVAL; - - if (memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN) == 0) { - id_t *tempRes = malloc(sizeof(*tempRes)); - if (tempRes == NULL) return ENOMEM; - memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID)); - (*tempRes) = ntohl(tempID); - (*result) = tempRes; - if (rec_type != NULL) { - (*rec_type) = MBR_REC_TYPE_USER; - } - return 0; - } else if (memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN) == 0) { - id_t *tempRes = malloc(sizeof(*tempRes)); - if (tempRes == NULL) return ENOMEM; - memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID)); - (*tempRes) = ntohl(tempID); + + tempRes = malloc(sizeof(*tempRes)); + if (tempRes == NULL) return ENOMEM; + + if (parse_compatibility_uuid(identifier, tempRes, rec_type)) { (*result) = tempRes; - if (rec_type != NULL) { - (*rec_type) = MBR_REC_TYPE_GROUP; - } return 0; } } @@ -247,8 +304,42 @@ mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_ break; } break; + + case ID_TYPE_USERNAME: + case ID_TYPE_GROUPNAME: + case ID_TYPE_NAME: +#if !DS_AVAILABLE + /* Convert compatibility UUIDs to names in-process. */ + if (id_type == ID_TYPE_UUID) { + if (identifier_size != sizeof(uuid_t)) return EINVAL; + if (compatibility_name_for_uuid(identifier, (char **)result, rec_type)) { + return 0; + } + } else if (id_type == ID_TYPE_UID) { + if (identifier_size != sizeof(tempID)) return EINVAL; + + tempID = *((id_t *) identifier); + if (compatibility_name_for_id(tempID, MBR_REC_TYPE_USER, (char **)result)) { + if (rec_type != NULL) { + (*rec_type) = MBR_REC_TYPE_USER; + } + return 0; + } + } else if (id_type == ID_TYPE_GID) { + if (identifier_size != sizeof(tempID)) return EINVAL; + + tempID = *((id_t *) identifier); + if (compatibility_name_for_id(tempID, MBR_REC_TYPE_GROUP, (char **)result)) { + if (rec_type != NULL) { + (*rec_type) = MBR_REC_TYPE_GROUP; + } + return 0; + } + } +#endif + break; } - + #if DS_AVAILABLE payload = xpc_dictionary_create(NULL, NULL, 0); if (payload == NULL) return EIO; -- 2.7.4