int main(int argc, char **argv) { CFDictionaryRef entities; CFStringRef key; CFDictionaryRef newProxy = NULL; CFStringRef pattern; CFMutableArrayRef patterns; CFStringRef primary = NULL; CFMutableDictionaryRef primary_proxy = NULL; CFArrayRef service_order = NULL; CFMutableDictionaryRef service_state_dict; CFDictionaryRef setup_global_ipv4; CFDictionaryRef state_global_ipv4; SCDynamicStoreRef store; _sc_log = FALSE; _sc_verbose = (argc > 1) ? TRUE : FALSE; store = SCDynamicStoreCreate(NULL, CFSTR("TEST"), NULL, NULL); // get IPv4, IPv6, and Proxies entities patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetProxies); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetProxies); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); entities = SCDynamicStoreCopyMultiple(store, NULL, patterns); CFRelease(patterns); service_state_dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryApplyFunction(entities, split, service_state_dict); CFRelease(entities); // get primary service ID key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); state_global_ipv4 = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (state_global_ipv4 != NULL) { primary = CFDictionaryGetValue(state_global_ipv4, kSCDynamicStorePropNetPrimaryService); if (primary != NULL) { CFDictionaryRef service_dict; // get proxy configuration for primary service service_dict = CFDictionaryGetValue(service_state_dict, primary); if (service_dict != NULL) { CFDictionaryRef service_proxy; service_proxy = CFDictionaryGetValue(service_dict, kSCEntNetProxies); if (service_proxy != NULL) { primary_proxy = CFDictionaryCreateMutableCopy(NULL, 0, service_proxy); CFDictionaryRemoveValue(primary_proxy, kSCPropInterfaceName); } } } } // get serviceOrder key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetIPv4); setup_global_ipv4 = SCDynamicStoreCopyValue(store, key); CFRelease(key); if (setup_global_ipv4 != NULL) { service_order = CFDictionaryGetValue(setup_global_ipv4, kSCPropNetServiceOrder); } // update proxy configuration proxy_configuration_init(CFBundleGetMainBundle()); newProxy = proxy_configuration_update(primary_proxy, service_state_dict, service_order, NULL); if (newProxy != NULL) { SCPrint(TRUE, stdout, CFSTR("%@\n"), newProxy); CFRelease(newProxy); } // cleanup if (setup_global_ipv4 != NULL) CFRelease(setup_global_ipv4); if (state_global_ipv4 != NULL) CFRelease(state_global_ipv4); CFRelease(service_state_dict); CFRelease(store); /* not reached */ exit(0); return 0; }
static CFStringRef copyVPNInterfaceNAP (char *interface_buf) { CFStringRef interf_key; CFMutableArrayRef interf_keys; CFDictionaryRef dict = NULL; CFIndex i; const void * keys_q[128]; void ** keys = (__typeof__(keys))keys_q; const void * values_q[128]; void ** values = (__typeof__(values))values_q; CFIndex n; CFStringRef vpn_if = NULL; CFStringRef result = NULL; if (!interface_buf) { return NULL; } if (gDynamicStore) { vpn_if = CFStringCreateWithCStringNoCopy(NULL, interface_buf, kCFStringEncodingASCII, kCFAllocatorNull); if (!vpn_if) { // if we could not initialize interface CFString goto done; } interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // get State:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); dict = SCDynamicStoreCopyMultiple(gDynamicStore, interf_keys, NULL); CFRelease(interf_keys); if (!dict) { // if we could not access the SCDynamicStore goto done; } // look for the service which matches the provided prefixes n = CFDictionaryGetCount(dict); if (n <= 0) { goto done; } if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); } CFDictionaryGetKeysAndValues(dict, (const void **)keys, (const void **)values); for (i=0; i < n; i++) { CFStringRef s_key = (CFStringRef)keys[i]; CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; CFDictionaryRef i_dict = NULL; CFStringRef nap; if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { continue; } i_dict = CFDictionaryGetValue(s_dict, KEY_VPNNETWORKLOCATION_INTERFINFO); if (!isA_CFDictionary(i_dict)) { continue; } nap = CFDictionaryGetValue(i_dict, KEY_VPNNETWORKLOCATION_SSID); if (nap) { result = CFStringCreateCopy(NULL, nap); SCLog(TRUE, LOG_INFO, CFSTR("%s: found nap %@, interf %s"), __FUNCTION__, result, interface_buf); goto done; } } done : if (vpn_if) CFRelease(vpn_if); if (keys != (__typeof__(keys))keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, values); } if (dict) CFRelease(dict); } return result; }
static void updateSCDynamicStore(SCPreferencesRef prefs) { CFStringRef current = NULL; CFDateRef date = NULL; CFMutableDictionaryRef dict = NULL; CFDictionaryRef global = NULL; CFIndex i; CFArrayRef keys; CFIndex n; CFStringRef pattern; CFMutableArrayRef patterns; CFDictionaryRef set = NULL; /* * initialize old preferences, new preferences, an array * of keys which have not changed, and an array of keys * to be removed (cleaned up). */ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); pattern = CFStringCreateWithFormat(NULL, NULL, CFSTR("^%@.*"), kSCDynamicStoreDomainSetup); CFArrayAppendValue(patterns, pattern); dict = (CFMutableDictionaryRef)SCDynamicStoreCopyMultiple(store, NULL, patterns); CFRelease(patterns); CFRelease(pattern); if (dict) { currentPrefs = CFDictionaryCreateMutableCopy(NULL, 0, dict); CFRelease(dict); } else { currentPrefs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } unchangedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); i = CFDictionaryGetCount(currentPrefs); if (i > 0) { const void **currentKeys; CFArrayRef array; currentKeys = CFAllocatorAllocate(NULL, i * sizeof(CFStringRef), 0); CFDictionaryGetKeysAndValues(currentPrefs, currentKeys, NULL); array = CFArrayCreate(NULL, currentKeys, i, &kCFTypeArrayCallBacks); removedPrefsKeys = CFArrayCreateMutableCopy(NULL, 0, array); CFRelease(array); CFAllocatorDeallocate(NULL, currentKeys); } else { removedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } /* * The "newPrefs" dictionary will contain the new / updated * configuration which will be written to the configuration cache. */ newPrefs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); /* * create status dictionary associated with current configuration * information including: * - current set "name" to cache * - time stamp indicating when the cache preferences were * last updated. */ dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); /* * load preferences */ keys = SCPreferencesCopyKeyList(prefs); if ((keys == NULL) || (CFArrayGetCount(keys) == 0)) { SCLog(TRUE, LOG_NOTICE, CFSTR("updateConfiguration(): no preferences.")); goto done; } /* * get "global" system preferences */ global = SCPreferencesGetValue(prefs, kSCPrefSystem); if (!global) { /* if no global preferences are defined */ goto getSet; } if (!isA_CFDictionary(global)) { SCLog(TRUE, LOG_ERR, CFSTR("updateConfiguration(): %@ is not a dictionary."), kSCPrefSystem); goto done; } /* flatten property list */ flatten(prefs, CFSTR("/"), global); getSet : /* * get current set name */ current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet); if (!current) { /* if current set not defined */ goto done; } if (!isA_CFString(current)) { SCLog(TRUE, LOG_ERR, CFSTR("updateConfiguration(): %@ is not a string."), kSCPrefCurrentSet); goto done; } /* * get current set */ set = SCPreferencesPathGetValue(prefs, current); if (!set) { /* if error with path */ SCLog(TRUE, LOG_ERR, CFSTR("%@ value (%@) not valid"), kSCPrefCurrentSet, current); goto done; } if (!isA_CFDictionary(set)) { SCLog(TRUE, LOG_ERR, CFSTR("updateConfiguration(): %@ is not a dictionary."), current); goto done; } /* flatten property list */ flatten(prefs, CFSTR("/"), set); CFDictionarySetValue(dict, kSCDynamicStorePropSetupCurrentSet, current); done : /* add last updated time stamp */ CFDictionarySetValue(dict, kSCDynamicStorePropSetupLastUpdated, date); /* add Setup: key */ CFDictionarySetValue(newPrefs, kSCDynamicStoreDomainSetup, dict); /* compare current and new preferences */ CFDictionaryApplyFunction(newPrefs, updateCache, NULL); /* remove those keys which have not changed from the update */ n = CFArrayGetCount(unchangedPrefsKeys); for (i = 0; i < n; i++) { CFStringRef key; key = CFArrayGetValueAtIndex(unchangedPrefsKeys, i); CFDictionaryRemoveValue(newPrefs, key); } /* Update the dynamic store */ #ifndef MAIN if (!SCDynamicStoreSetMultiple(store, newPrefs, removedPrefsKeys, NULL)) { SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreSetMultiple() failed: %s"), SCErrorString(SCError())); } #else // !MAIN SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStore\nset: %@\nremove: %@\n"), newPrefs, removedPrefsKeys); #endif // !MAIN CFRelease(currentPrefs); CFRelease(newPrefs); CFRelease(unchangedPrefsKeys); CFRelease(removedPrefsKeys); if (dict) CFRelease(dict); if (date) CFRelease(date); if (keys) CFRelease(keys); return; }
int checkVPNInterfaceOrServiceBlocked (const char *location, char *interface_buf) { // check to see if interface is captive: if so, bail if the interface is not ready. if (check_interface_captive_and_not_ready(gDynamicStore, interface_buf)) { // TODO: perhaps we should wait for a few seconds? return true; } // return 1, if this is a delete event, and; // TODO: add support for IPv6 <rdar://problem/5920237> // walk Setup:/Network/Service/* and check if there are service entries referencing this interface. e.g. Setup:/Network/Service/44DB8790-0177-4F17-8D4E-37F9413D1D87/Interface:DeviceName == interface, other_serv_found = 1 // Setup:/Network/Interface/"interface"/AirPort:'PowerEnable' == 0 || Setup:/Network/Interface/"interface"/IPv4 is missing, interf_down = 1 if (gDynamicStore) { CFStringRef interf_key; CFMutableArrayRef interf_keys; CFStringRef pattern; CFMutableArrayRef patterns; CFDictionaryRef dict = NULL; CFIndex i; const void * keys_q[128]; const void ** keys = keys_q; const void * values_q[128]; const void ** values = values_q; CFIndex n; CFStringRef vpn_if; int other_serv_found = 0, interf_down = 0; vpn_if = CFStringCreateWithCStringNoCopy(NULL, interface_buf, kCFStringEncodingASCII, kCFAllocatorNull); if (!vpn_if) { // if we could not initialize interface CFString syslog(LOG_NOTICE, "%s: failed to initialize interface CFString", location); goto done; } interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // get Setup:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainSetup, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get State:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get Setup:/Network/Service/*/Interface pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); // get Setup:/Network/Service/*/IPv4 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); dict = SCDynamicStoreCopyMultiple(gDynamicStore, interf_keys, patterns); CFRelease(interf_keys); CFRelease(patterns); if (!dict) { // if we could not access the SCDynamicStore syslog(LOG_NOTICE, "%s: failed to initialize SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } // look for the service which matches the provided prefixes n = CFDictionaryGetCount(dict); if (n <= 0) { syslog(LOG_NOTICE, "%s: empty SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); } CFDictionaryGetKeysAndValues(dict, keys, values); for (i=0; i < n; i++) { CFStringRef s_key = (CFStringRef)keys[i]; CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; CFStringRef s_if; if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { continue; } if (CFStringHasSuffix(s_key, kSCEntNetInterface)) { // is a Service Interface entity s_if = CFDictionaryGetValue(s_dict, kSCPropNetInterfaceDeviceName); if (isA_CFString(s_if) && CFEqual(vpn_if, s_if)) { CFArrayRef components; CFStringRef serviceIDRef = NULL, serviceKey = NULL; other_serv_found = 1; // extract service ID components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); if (CFArrayGetCount(components) > 3) { serviceIDRef = CFArrayGetValueAtIndex(components, 3); //if (new key) Setup:/Network/Service/service_id/IPv4 is missing, then interf_down = 1 serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainSetup, serviceIDRef, kSCEntNetIPv4); if (!serviceKey || !CFDictionaryGetValue(dict, serviceKey)) { syslog(LOG_NOTICE, "%s: detected disabled IPv4 Config", location); interf_down = 1; } if (serviceKey) CFRelease(serviceKey); } if (components) CFRelease(components); if (interf_down) break; } continue; } else if (CFStringHasSuffix(s_key, kSCEntNetAirPort)) { // Interface/<vpn_if>/Airport entity if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainSetup)) { CFBooleanRef powerEnable = CFDictionaryGetValue(s_dict, kSCPropNetAirPortPowerEnabled); if (isA_CFBoolean(powerEnable) && CFEqual(powerEnable, kCFBooleanFalse)) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerEnable == FALSE", location); interf_down = 1; break; } } else if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainState)) { UInt16 temp; CFNumberRef airStatus = CFDictionaryGetValue(s_dict, CFSTR("Power Status")); if (isA_CFNumber(airStatus) && CFNumberGetValue(airStatus, kCFNumberShortType, &temp)) { if (temp ==0) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerStatus == 0", location); } } } continue; } } if (vpn_if) CFRelease(vpn_if); if (keys != keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, values); } done : if (dict) CFRelease(dict); return (other_serv_found == 0 || interf_down == 1); } return 0; }