]> git.saurik.com Git - apple/libinfo.git/commitdiff
Libinfo-503.50.4.tar.gz macos-10124 macos-10125 macos-10126 v503.50.4
authorApple <opensource@apple.com>
Wed, 18 Jan 2017 19:11:50 +0000 (19:11 +0000)
committerApple <opensource@apple.com>
Wed, 18 Jan 2017 19:11:50 +0000 (19:11 +0000)
Libinfo.xcodeproj/project.pbxproj
lookup.subproj/si_getaddrinfo.c
membership.subproj/membership.c

index 0cd0e5e7c674bf8a3aa88e1afb6c0a14ff1964b3..c3189894ea2155f75be9347642c73669123c62eb 100644 (file)
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                OTHER_CFLAGS = "";
                                VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wno-error=deprecated-declarations";
                                WARNING_LDFLAGS = "-Wall";
                        };
                        name = Release;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                OTHER_CFLAGS = "-DDEBUG=1";
                                VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wno-error=deprecated-declarations";
                                WARNING_LDFLAGS = "-Wall";
                        };
                        name = Debug;
index 27ab2c81feb2b471e84ce04a2f08e8623e56e1df..6feaa510a83b1ac75a94a2d92040b2292ebd1b17 100644 (file)
@@ -31,6 +31,7 @@
 #include <netinet/in.h>
 #include <network/sa_compare.h>
 #include <network/nat64.h>
+#include <network/path_evaluation.h>
 #include <arpa/inet.h>
 #include <ifaddrs.h>
 #include <net/if.h>
@@ -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);
        }
 
index ff37c3cc278196fa5d2ef2fd868170f2db4bdb63..6f4b6cf46c6b245a42738ccd6b645dca8fab4b43 100644 (file)
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
+#include <unistd.h>
 #include <mach/mach.h>
 #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;