]> git.saurik.com Git - apple/configd.git/blobdiff - Plugins/IPMonitor/proxy-configuration.c
configd-1061.101.1.tar.gz
[apple/configd.git] / Plugins / IPMonitor / proxy-configuration.c
index 76d60fac9f07fc09d1321439df1cfb98c64a5953..9116f422d1adc0af16025584f381f8799c56789a 100644 (file)
@@ -1,15 +1,15 @@
 /*
- * Copyright (c) 2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2011-2017 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,7 +17,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
@@ -37,6 +37,7 @@
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
+#include "ip_plugin.h"
 
 
 #define DEFAULT_MATCH_ORDER    200000   /* match order for the "default" proxy configuration */
@@ -215,7 +216,7 @@ add_supplemental_proxies(CFMutableArrayRef proxies, CFDictionaryRef services, CF
 
                defaultOrder = DEFAULT_MATCH_ORDER
                               - (DEFAULT_MATCH_ORDER / 2)
-                              + ((DEFAULT_MATCH_ORDER / 1000) * i);
+                              + ((DEFAULT_MATCH_ORDER / 1000) * (uint32_t)i);
                if ((n_order > 0) &&
                    !CFArrayContainsValue(service_order, CFRangeMake(0, n_order), keys[i])) {
                        // push out services not specified in service order
@@ -238,6 +239,7 @@ add_supplemental_proxies(CFMutableArrayRef proxies, CFDictionaryRef services, CF
 static CFComparisonResult
 compareBySearchOrder(const void *val1, const void *val2, void *context)
 {
+#pragma unused(context)
        CFDictionaryRef proxy1  = (CFDictionaryRef)val1;
        CFDictionaryRef proxy2  = (CFDictionaryRef)val2;
        CFNumberRef     num1;
@@ -247,13 +249,13 @@ compareBySearchOrder(const void *val1, const void *val2, void *context)
 
        num1 = CFDictionaryGetValue(proxy1, PROXY_MATCH_ORDER_KEY);
        if (!isA_CFNumber(num1) ||
-           !CFNumberGetValue(num1, kCFNumberIntType, &order1)) {
+           !CFNumberGetValue(num1, kCFNumberSInt32Type, &order1)) {
                order1 = DEFAULT_MATCH_ORDER;
        }
 
        num2 = CFDictionaryGetValue(proxy2, PROXY_MATCH_ORDER_KEY);
        if (!isA_CFNumber(num2) ||
-           !CFNumberGetValue(num2, kCFNumberIntType, &order2)) {
+           !CFNumberGetValue(num2, kCFNumberSInt32Type, &order2)) {
                order2 = DEFAULT_MATCH_ORDER;
        }
 
@@ -263,8 +265,8 @@ compareBySearchOrder(const void *val1, const void *val2, void *context)
                    CFDictionaryGetValueIfPresent(proxy2, ORDER_KEY, (const void **)&num2) &&
                    isA_CFNumber(num1) &&
                    isA_CFNumber(num2) &&
-                   CFNumberGetValue(num1, kCFNumberIntType, &order1) &&
-                   CFNumberGetValue(num2, kCFNumberIntType, &order2)) {
+                   CFNumberGetValue(num1, kCFNumberSInt32Type, &order1) &&
+                   CFNumberGetValue(num2, kCFNumberSInt32Type, &order2)) {
                        if (order1 == order2) {
                                return kCFCompareEqualTo;
                        } else {
@@ -294,6 +296,7 @@ isSupplementalProxy(CFDictionaryRef proxy)
 static CFArrayRef
 copy_supplemental_proxies(CFArrayRef proxies, Boolean skip)
 {
+#pragma unused(skip)
        CFIndex                 i;
        CFIndex                 n_proxies;
        CFMutableArrayRef       supplemental    = NULL;
@@ -323,8 +326,8 @@ copy_supplemental_proxies(CFArrayRef proxies, Boolean skip)
 }
 
 
-static CFDictionaryRef
-copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
+static CFArrayRef
+service_order_copy_all(CFDictionaryRef services, CFArrayRef service_order)
 {
        const void *            keys_q[N_QUICK];
        const void **           keys    = keys_q;
@@ -332,11 +335,12 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
        CFIndex                 n_order;
        CFIndex                 n_services;
        CFMutableArrayRef       order;
-       CFMutableDictionaryRef  scoped  = NULL;
 
+       // ensure that we process all services in order
        n_services = isA_CFDictionary(services) ? CFDictionaryGetCount(services) : 0;
        if (n_services == 0) {
-               return NULL;            // if no services
+               // if no services
+               return NULL;
        }
 
        // ensure that we process all services in order
@@ -344,7 +348,7 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
        n_order = isA_CFArray(service_order) ? CFArrayGetCount(service_order) : 0;
        if (n_order > 0) {
                order = CFArrayCreateMutableCopy(NULL, 0, service_order);
-       } else{
+       } else {
                order = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        }
 
@@ -353,7 +357,7 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
        }
        CFDictionaryGetKeysAndValues(services, keys, NULL);
        for (i = 0; i < n_services; i++) {
-               CFStringRef     serviceID = (CFStringRef)keys[i];
+               CFStringRef     serviceID       = (CFStringRef)keys[i];
 
                if (!CFArrayContainsValue(order, CFRangeMake(0, n_order), serviceID)) {
                        CFArrayAppendValue(order, serviceID);
@@ -364,13 +368,100 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
                CFAllocatorDeallocate(NULL, keys);
        }
 
+       return order;
+}
+
+
+static CFDictionaryRef
+copy_app_layer_vpn_proxies(CFDictionaryRef services, CFArrayRef order, CFDictionaryRef services_info)
+{
+       CFMutableDictionaryRef  app_layer_proxies       = NULL;
+       CFIndex                 i;
+       CFIndex                 n_order;
+
+       if (!isA_CFDictionary(services_info)) {
+               return NULL;
+       }
+
        // iterate over services
 
+       n_order = isA_CFArray(order) ? CFArrayGetCount(order) : 0;
        for (i = 0; i < n_order; i++) {
+               CFMutableDictionaryRef  newProxy;
                CFDictionaryRef         proxy;
+               CFDictionaryRef         service;
+               CFStringRef             serviceID;
+               CFNumberRef             serviceSpecificIdentifier;
+               int                     serviceIdentifier = 0;
+               CFStringRef             serviceIdentifierString;
+
+               serviceID = CFArrayGetValueAtIndex(order, i);
+               service = CFDictionaryGetValue(services, serviceID);
+               if (!isA_CFDictionary(service)) {
+                       // if no service
+                       continue;
+               }
+
+               proxy = CFDictionaryGetValue(service, kSCEntNetProxies);
+               if (!isA_CFDictionary(proxy)) {
+                       // if no proxy
+                       continue;
+               }
+
+               serviceSpecificIdentifier = CFDictionaryGetValue(proxy, kSCPropNetProxiesServiceSpecific);
+               if (!isA_CFNumber(serviceSpecificIdentifier) ||
+                   !CFNumberGetValue(serviceSpecificIdentifier, kCFNumberIntType, &serviceIdentifier) ||
+                   serviceIdentifier == 0) {
+                       // if not a service-specific proxy configuration
+                       continue;
+               }
+
+               serviceIdentifierString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), serviceIdentifier);
+               if (serviceIdentifierString == NULL) {
+                       continue;
+               }
+               if ((app_layer_proxies != NULL) &&
+                   CFDictionaryContainsKey(app_layer_proxies, serviceIdentifierString)) {
+                       // if we've already processed this [app_layer_proxies] identifier
+                       CFRelease(serviceIdentifierString);
+                       continue;
+               }
+
+               // add [app_layer_proxies] proxy entry
+               newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
+               CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchDomains);
+               CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchOrders);
+               CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesServiceSpecific);
+               if (app_layer_proxies == NULL) {
+                       app_layer_proxies = CFDictionaryCreateMutable(NULL,
+                                                                     0,
+                                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                                     &kCFTypeDictionaryValueCallBacks);
+               }
+               CFDictionarySetValue(app_layer_proxies, serviceIdentifierString, newProxy);
+               CFRelease(serviceIdentifierString);
+               CFRelease(newProxy);
+       }
+
+       return app_layer_proxies;
+}
+
+
+static CFDictionaryRef
+copy_scoped_proxies(CFDictionaryRef services, CFArrayRef order)
+{
+       CFIndex                 i;
+       CFIndex                 n_order;
+       CFMutableDictionaryRef  scoped  = NULL;
+
+       // iterate over services
+
+       n_order = isA_CFArray(order) ? CFArrayGetCount(order) : 0;
+       for (i = 0; i < n_order; i++) {
                char                    if_name[IF_NAMESIZE];
                CFStringRef             interface;
                CFMutableDictionaryRef  newProxy;
+               CFDictionaryRef         proxy;
                CFDictionaryRef         service;
                CFStringRef             serviceID;
 
@@ -402,7 +493,7 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
                                             if_name,
                                             sizeof(if_name),
                                             kCFStringEncodingASCII) == NULL) ||
-                   ((if_nametoindex(if_name)) == 0)) {
+                   ((my_if_nametoindex(if_name)) == 0)) {
                        // if interface index not available
                        continue;
                }
@@ -425,7 +516,6 @@ copy_scoped_proxies(CFDictionaryRef services, CFArrayRef service_order)
                CFRelease(interface);
        }
 
-       CFRelease(order);
        return scoped;
 }
 
@@ -453,7 +543,7 @@ add_default_proxy(CFMutableArrayRef proxies,
        // ensure that the default proxy has a search order
 
        if (!isA_CFNumber(order) ||
-           !CFNumberGetValue(order, kCFNumberIntType, &myOrder)) {
+           !CFNumberGetValue(order, kCFNumberSInt32Type, &myOrder)) {
                myOrder = DEFAULT_MATCH_ORDER;
                order = CFNumberCreate(NULL, kCFNumberIntType, &myOrder);
                CFDictionarySetValue(myDefault, PROXY_MATCH_ORDER_KEY, order);
@@ -548,7 +638,8 @@ __private_extern__
 CF_RETURNS_RETAINED CFDictionaryRef
 proxy_configuration_update(CFDictionaryRef     defaultProxy,
                           CFDictionaryRef      services,
-                          CFArrayRef           serviceOrder)
+                          CFArrayRef           serviceOrder,
+                          CFDictionaryRef      servicesInfo)
 {
        CFIndex                 i;
        CFMutableDictionaryRef  myDefault;
@@ -618,8 +709,10 @@ proxy_configuration_update(CFDictionaryRef defaultProxy,
        // establish proxy configuration
 
        if (n_proxies > 0) {
+               CFDictionaryRef         app_layer;
                CFDictionaryRef         scoped;
-               Boolean                 skip    = FALSE;
+               CFArrayRef              serviceOrderAll;
+               Boolean                 skip            = FALSE;
                CFArrayRef              supplemental;
 
                proxy = CFArrayGetValueAtIndex(proxies, 0);
@@ -636,6 +729,8 @@ proxy_configuration_update(CFDictionaryRef  defaultProxy,
                                                             &kCFTypeDictionaryValueCallBacks);
                }
 
+               serviceOrderAll = service_order_copy_all(services, serviceOrder);
+
                // collect (and add) any "supplemental" proxy configurations
 
                supplemental = copy_supplemental_proxies(proxies, skip);
@@ -646,11 +741,23 @@ proxy_configuration_update(CFDictionaryRef        defaultProxy,
 
                // collect (and add) any "scoped" proxy configurations
 
-               scoped = copy_scoped_proxies(services, serviceOrder);
+               scoped = copy_scoped_proxies(services, serviceOrderAll);
                if (scoped != NULL) {
                        CFDictionarySetValue(newProxy, kSCPropNetProxiesScoped, scoped);
                        CFRelease(scoped);
                }
+
+               // collect (and add) any "services" based proxy configurations
+
+               app_layer = copy_app_layer_vpn_proxies(services, serviceOrderAll, servicesInfo);
+               if (app_layer != NULL) {
+                       CFDictionarySetValue(newProxy, kSCPropNetProxiesServices, app_layer);
+                       CFRelease(app_layer);
+               }
+
+               if (serviceOrderAll != NULL) {
+                       CFRelease(serviceOrderAll);
+               }
        } else {
                newProxy = NULL;
        }
@@ -866,7 +973,8 @@ main(int argc, char **argv)
        proxy_configuration_init(CFBundleGetMainBundle());
        newProxy = proxy_configuration_update(primary_proxy,
                                              service_state_dict,
-                                             service_order);
+                                             service_order,
+                                             NULL);
        if (newProxy != NULL) {
                SCPrint(TRUE, stdout, CFSTR("%@\n"), newProxy);
                CFRelease(newProxy);