X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/4f125ff561e6fa1bd12b93c65dc5fa8e3323fd9a..HEAD:/Plugins/PreferencesMonitor/prefsmon.c diff --git a/Plugins/PreferencesMonitor/prefsmon.c b/Plugins/PreferencesMonitor/prefsmon.c index 84e9476..31ce760 100644 --- a/Plugins/PreferencesMonitor/prefsmon.c +++ b/Plugins/PreferencesMonitor/prefsmon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008, 2010, 2012-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2008, 2010, 2012-2020 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -36,33 +36,29 @@ #include -#include -#include #include -#include #include - -#define SC_LOG_HANDLE __log_PreferencesMonitor() +#define SC_LOG_HANDLE __log_PreferencesMonitor #define SC_LOG_HANDLE_TYPE static #include #include #include +#include "SCNetworkConfigurationInternal.h" #include "plugin_shared.h" -#include - - /* globals */ static SCPreferencesRef prefs = NULL; static SCDynamicStoreRef store = NULL; /* InterfaceNamer[.plugin] monitoring globals */ -Boolean haveConfiguration = FALSE; +static CFMutableArrayRef excluded_interfaces = NULL; // of SCNetworkInterfaceRef +static CFMutableArrayRef excluded_names = NULL; // of CFStringRef (BSD name) +static Boolean haveConfiguration = FALSE; static CFStringRef namerKey = NULL; -static CFMutableArrayRef preconfigured_names = NULL; // of CFStringRef (BSD name) static CFMutableArrayRef preconfigured_interfaces= NULL; // of SCNetworkInterfaceRef +static CFMutableArrayRef preconfigured_names = NULL; // of CFStringRef (BSD name) /* KernelEventMonitor[.plugin] monitoring globals */ static CFStringRef interfacesKey = NULL; @@ -74,7 +70,6 @@ static CFMutableArrayRef unchangedPrefsKeys; /* new prefs keys which match curre static CFMutableArrayRef removedPrefsKeys; /* old prefs keys to be removed */ static Boolean rofs = FALSE; -static Boolean restorePrefs = FALSE; #define MY_PLUGIN_NAME "PreferencesMonitor" #define MY_PLUGIN_ID CFSTR("com.apple.SystemConfiguration." MY_PLUGIN_NAME) @@ -87,7 +82,7 @@ updateConfiguration(SCPreferencesRef prefs, static os_log_t -__log_PreferencesMonitor() +__log_PreferencesMonitor(void) { static os_log_t log = NULL; @@ -99,116 +94,37 @@ __log_PreferencesMonitor() } -static Boolean -restorePreferences() +static void +savePastConfiguration(CFStringRef old_model) { - Boolean ok = FALSE; - CFStringRef currentModel = NULL; - CFMutableStringRef modelPrefixStr = NULL; - CFArrayRef keyList = NULL; - CFIndex keyListCount; - CFIndex idx; - Boolean modified = FALSE; - int sc_status = kSCStatusFailed; - - while (TRUE) { - ok = SCPreferencesLock(prefs, TRUE); - if (ok) { - break; - } + CFDictionaryRef system; - sc_status = SCError(); - if (sc_status == kSCStatusStale) { - SCPreferencesSynchronize(prefs); - } else { - SC_log(LOG_NOTICE, "Could not acquire network configuration lock: %s", - SCErrorString(sc_status)); - return FALSE; - } + // save "/System" (e.g. host names) + system = SCPreferencesGetValue(prefs, kSCPrefSystem); + if (system != NULL) { + CFRetain(system); } - keyList = SCPreferencesCopyKeyList(prefs); - if (keyList == NULL) { - goto error; - } + // save the [previous devices] configuration + __SCNetworkConfigurationSaveModel(prefs, old_model); - currentModel = _SC_hw_model(FALSE); - if (currentModel == NULL) { - goto error; + if (system != NULL) { + // and retain "/System" (e.g. host names) + SCPreferencesSetValue(prefs, kSCPrefSystem, system); + CFRelease(system); } - /* Create "model:" string for prefix-check */ - modelPrefixStr = CFStringCreateMutableCopy(NULL, 0, currentModel); - CFStringAppend(modelPrefixStr, CFSTR(":")); - - keyListCount = CFArrayGetCount(keyList); - for (idx = 0; idx < keyListCount; idx++) { - CFStringRef existingKey = CFArrayGetValueAtIndex(keyList, idx); - CFStringRef key; - CFArrayRef splitKey = NULL; - CFPropertyListRef value; - - if (isA_CFString(existingKey) == NULL) { - continue; - } - - if (!CFStringHasPrefix(existingKey, modelPrefixStr)) { - continue; - } - - splitKey = CFStringCreateArrayBySeparatingStrings(NULL, existingKey, CFSTR(":")); - key = CFArrayGetValueAtIndex(splitKey, 1); - value = SCPreferencesGetValue(prefs, existingKey); - SCPreferencesSetValue(prefs, key, value); - SCPreferencesRemoveValue(prefs, existingKey); - modified = TRUE; - CFRelease(splitKey); - } - - if (modified) { - SCPreferencesRef ni_prefs = NULL; - ni_prefs = SCPreferencesCreate(NULL, MY_PLUGIN_ID, CFSTR("NetworkInterfaces.plist")); - if (ni_prefs == NULL) { - goto error; - } - - ok = _SCNetworkConfigurationCheckValidityWithPreferences(prefs, ni_prefs, NULL); - CFRelease(ni_prefs); - - //Commit the changes only if prefs files valid - if (ok) { - if (!SCPreferencesCommitChanges(prefs)) { - if (SCError() != EROFS) { - SC_log(LOG_NOTICE, "SCPreferencesCommitChanges() failed: %s", - SCErrorString(SCError())); - } - goto error; - - } - - (void) SCPreferencesApplyChanges(prefs); - } - } - -error: - (void) SCPreferencesUnlock(prefs); - - if (keyList != NULL) { - CFRelease(keyList); - } - if (modelPrefixStr != NULL) { - CFRelease(modelPrefixStr); - } - - return modified; + return; } + static Boolean establishNewPreferences() { SCNetworkSetRef current = NULL; CFStringRef new_model; Boolean ok = FALSE; + CFStringRef old_model; int sc_status = kSCStatusFailed; SCNetworkSetRef set = NULL; Boolean updated = FALSE; @@ -229,58 +145,18 @@ establishNewPreferences() } } - /* Ensure that the preferences has the new model */ + // check if we need to regenerate the configuration for a new model + old_model = SCPreferencesGetValue(prefs, MODEL); new_model = _SC_hw_model(FALSE); - - /* Need to regenerate the new configuration for new model */ - if (new_model != NULL) { - CFStringRef old_model; - - old_model = SCPreferencesGetValue(prefs, MODEL); - if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) { - CFIndex count; - CFIndex index; - CFArrayRef keys; - - keys = SCPreferencesCopyKeyList(prefs); - count = (keys != NULL) ? CFArrayGetCount(keys) : 0; - // if new hardware - for (index = 0; index < count; index++) { - CFStringRef existing_key; - - existing_key = CFArrayGetValueAtIndex(keys, index); - if (isA_CFString(existing_key) != NULL) { - CFStringRef new_key; - CFPropertyListRef value; - - /* If it already contains a Model - or if it already contains a MODEL:KEY key skip it*/ - if (CFEqual(existing_key, MODEL) - || CFStringFind(existing_key, CFSTR(":"), 0).location - != kCFNotFound) { - continue; - } - - value = SCPreferencesGetValue(prefs, existing_key); - - /* Create a new key as OLD_MODEL:OLD_KEY */ - new_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"), - old_model, existing_key); - SCPreferencesSetValue(prefs, new_key, value); - if (!CFEqual(existing_key, kSCPrefSystem)) { - /* preserve existing host names */ - SCPreferencesRemoveValue(prefs, existing_key); - } - CFRelease(new_key); - } - } - - if (keys != NULL) { - CFRelease(keys); - } - } - /* Set the new model */ - SCPreferencesSetValue(prefs, MODEL, new_model); + if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) { + SC_log(LOG_NOTICE, "Hardware model changed\n" + " created on \"%@\"\n" + " now on \"%@\"", + old_model, + new_model); + + // save (and clean) the configuration that was created for "other" hardware + savePastConfiguration(old_model); } current = SCNetworkSetCopyCurrent(prefs); @@ -388,23 +264,73 @@ watchSCDynamicStore() static Boolean -previousConfigurationAvailable() +findInterfaces(CFArrayRef interfaces, CFMutableArrayRef *matched_interfaces, CFMutableArrayRef *matched_names) { - CFStringRef backupKey = NULL; - CFStringRef currentModel = NULL; - CFPropertyListRef properties = NULL; + CFIndex n; + CFIndex nx = 0; + Boolean updated = FALSE; - currentModel = _SC_hw_model(FALSE); - if (currentModel == NULL) { - goto done; + // start clean + if (*matched_interfaces != NULL) { + CFRelease(*matched_interfaces); + *matched_interfaces = NULL; } + if (*matched_names != NULL) { + nx = CFArrayGetCount(*matched_names); + CFRelease(*matched_names); + *matched_names = NULL; + } + + n = (interfaces != NULL) ? CFArrayGetCount(interfaces) : 0; + for (CFIndex i = 0; i < n; i++) { + CFStringRef bsdName = CFArrayGetValueAtIndex(interfaces, i); + SCNetworkInterfaceRef interface; + + for (int retry = 0; retry < 10; retry++) { + if (retry != 0) { + // add short delay (before retry) + usleep(20 * 1000); // 20ms + } + + interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces); + if (interface == NULL) { + SC_log(LOG_ERR, "could not create network interface for %@", bsdName); + } else if (_SCNetworkInterfaceGetIOPath(interface) == NULL) { + SC_log(LOG_ERR, "could not get IOPath for %@", bsdName); + CFRelease(interface); + interface = NULL; + } + + if (interface == NULL) { + // if SCNetworkInterface not [currently] available + continue; + } - /* Currently relying only if a backup of "Sets" is present */ - backupKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:Sets"), currentModel); - properties = SCPreferencesGetValue(prefs, backupKey); - CFRelease(backupKey); -done: - return (properties != NULL); + // keep track of the interface name (quicker than having to iterate the list + // of SCNetworkInterfaces, extract the name, and compare). + if (*matched_names == NULL) { + *matched_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(*matched_names, bsdName); + + if (*matched_interfaces == NULL) { + *matched_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(*matched_interfaces, interface); + CFRelease(interface); + + updated = TRUE; + break; + } + } + + // check if all interfaces were detached + n = (*matched_names != NULL) ? CFArrayGetCount(*matched_names) : 0; + if ((nx > 0) && (n == 0)) { + updated = TRUE; + } + + return updated; } @@ -420,11 +346,14 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) /* * Capture/process InterfaceNamer[.bundle] info * 1. check if IORegistry "quiet", "timeout" - * 2. update list of named pre-configured interfaces + * 2. update list of excluded interfaces (e.g. those requiring that + * the attached host be trusted) + * 3. update list of named pre-configured interfaces */ dict = SCDynamicStoreCopyValue(store, namerKey); if (dict != NULL) { if (isA_CFDictionary(dict)) { + CFArrayRef excluded; CFArrayRef preconfigured; if (CFDictionaryContainsKey(dict, kInterfaceNamerKey_Quiet)) { @@ -434,78 +363,35 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) timeout = TRUE; } - preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces); - preconfigured = isA_CFArray(preconfigured); - if (!_SC_CFEqual(preconfigured, preconfigured_names)) { - CFIndex n; - CFIndex nx = 0; - - // start clean - if (preconfigured_names != NULL) { - nx = CFArrayGetCount(preconfigured_names); - CFRelease(preconfigured_names); - preconfigured_names = NULL; - } - if (preconfigured_interfaces != NULL) { - CFRelease(preconfigured_interfaces); - preconfigured_interfaces = NULL; - } - - // add pre-configured interfaces - n = (preconfigured != NULL) ? CFArrayGetCount(preconfigured) : 0; - for (CFIndex i = 0; i < n; i++) { - CFStringRef bsdName = CFArrayGetValueAtIndex(preconfigured, i); - SCNetworkInterfaceRef interface; - - for (int retry = 0; retry < 10; retry++) { - if (retry != 0) { - // add short delay (before retry) - usleep(20 * 1000); // 20ms - } - - interface = _SCNetworkInterfaceCreateWithBSDName(NULL, bsdName, kIncludeNoVirtualInterfaces); - if (interface == NULL) { - SC_log(LOG_ERR, "could not create network interface for %@", bsdName); - } else if (_SCNetworkInterfaceGetIOPath(interface) == NULL) { - SC_log(LOG_ERR, "could not get IOPath for %@", bsdName); - CFRelease(interface); - interface = NULL; - } - - if (interface != NULL) { - // if we have an interface - break; - } - } + excluded = CFDictionaryGetValue(dict, kInterfaceNamerKey_ExcludedInterfaces); + excluded = isA_CFArray(excluded); + if (!_SC_CFEqual(excluded, excluded_names)) { + Boolean excluded_updated; - if (interface == NULL) { - // if SCNetworkInterface not [currently] available - continue; - } - - // keep track of the interface name (quicker than having to iterate the list - // of SCNetworkInterfaces, extract the name, and compare). - if (preconfigured_names == NULL) { - preconfigured_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - } - CFArrayAppendValue(preconfigured_names, bsdName); + excluded_updated = findInterfaces(excluded, &excluded_interfaces, &excluded_names); + if (excluded_updated) { + CFStringRef interfaces = CFSTR(""); - if (preconfigured_interfaces == NULL) { - preconfigured_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + // report [updated] pre-configured interfaces + if (excluded_names != NULL) { + interfaces = CFStringCreateByCombiningStrings(NULL, excluded_names, CFSTR(",")); + } else { + CFRetain(interfaces); } - CFArrayAppendValue(preconfigured_interfaces, interface); - CFRelease(interface); + SC_log(LOG_INFO, "excluded interface list changed: %@", interfaces); + CFRelease(interfaces); updated = TRUE; } + } - // check if all pre-configured interfaces were detached - n = (preconfigured_names != NULL) ? CFArrayGetCount(preconfigured_names) : 0; - if ((nx > 0) && (n == 0)) { - updated = TRUE; - } + preconfigured = CFDictionaryGetValue(dict, kInterfaceNamerKey_PreConfiguredInterfaces); + preconfigured = isA_CFArray(preconfigured); + if (!_SC_CFEqual(preconfigured, preconfigured_names)) { + Boolean preconfigured_updated; - if (updated) { + preconfigured_updated = findInterfaces(preconfigured, &preconfigured_interfaces, &preconfigured_names); + if (preconfigured_updated) { CFStringRef interfaces = CFSTR(""); // report [updated] pre-configured interfaces @@ -516,6 +402,8 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) } SC_log(LOG_INFO, "pre-configured interface list changed: %@", interfaces); CFRelease(interfaces); + + updated = TRUE; } } } @@ -536,11 +424,6 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) (void) establishNewPreferences(); - if (restorePrefs) { - (void) restorePreferences(); - restorePrefs = FALSE; - } - if (timeout && (logged++ == 0)) { SC_log(LOG_ERR, "Network configuration creation timed out waiting for IORegistry"); } @@ -680,39 +563,74 @@ flatten(SCPreferencesRef prefs, } -static CF_RETURNS_RETAINED CFStringRef -copyInterfaceUUID(CFStringRef bsdName) +static void +excludeConfigurations(SCPreferencesRef prefs) { - union { - unsigned char sha1_bytes[CC_SHA1_DIGEST_LENGTH]; - CFUUIDBytes uuid_bytes; - } bytes; - CC_SHA1_CTX ctx; - char if_name[IF_NAMESIZE]; - CFUUIDRef uuid; - CFStringRef uuid_str; - - // start with interface name - bzero(&if_name, sizeof(if_name)); - (void) _SC_cfstring_to_cstring(bsdName, - if_name, - sizeof(if_name), - kCFStringEncodingASCII); - - // create SHA1 hash - bzero(&bytes, sizeof(bytes)); - CC_SHA1_Init(&ctx); - CC_SHA1_Update(&ctx, - if_name, - sizeof(if_name)); - CC_SHA1_Final(bytes.sha1_bytes, &ctx); - - // create UUID string - uuid = CFUUIDCreateFromUUIDBytes(NULL, bytes.uuid_bytes); - uuid_str = CFUUIDCreateString(NULL, uuid); - CFRelease(uuid); - - return uuid_str; + Boolean ok; + CFRange range; + CFArrayRef services; + SCNetworkSetRef set; + + range = CFRangeMake(0, + (excluded_names != NULL) ? CFArrayGetCount(excluded_names) : 0); + if (range.length == 0) { + // if no [excluded] interfaces + return; + } + + set = SCNetworkSetCopyCurrent(prefs); + if (set == NULL) { + // if no current set + return; + } + + /* + * Check for (and remove) any network services associated with + * an excluded interface from the prefs. + */ + services = SCNetworkSetCopyServices(set); + if (services != NULL) { + CFIndex n; + + n = CFArrayGetCount(services); + for (CFIndex i = 0; i < n; i++) { + CFStringRef bsdName; + SCNetworkInterfaceRef interface; + SCNetworkServiceRef service; + + service = CFArrayGetValueAtIndex(services, i); + + interface = SCNetworkServiceGetInterface(service); + if (interface == NULL) { + // if no interface + continue; + } + + bsdName = SCNetworkInterfaceGetBSDName(interface); + if (bsdName == NULL) { + // if no interface name + continue; + } + + if (!CFArrayContainsValue(excluded_names, range, bsdName)) { + // if not excluded + continue; + } + + // remove [excluded] network service from the prefs + SC_log(LOG_NOTICE, "excluding network service for %@", bsdName); + ok = SCNetworkSetRemoveService(set, service); + if (!ok) { + SC_log(LOG_ERR, "SCNetworkSetRemoveService() failed: %s", + SCErrorString(SCError())); + } + } + + CFRelease(services); + } + + CFRelease(set); + return; } @@ -802,42 +720,12 @@ updatePreConfiguredConfiguration(SCPreferencesRef prefs) CFStringRef bsdName; SCNetworkInterfaceRef interface = CFArrayGetValueAtIndex(preconfigured_interfaces, i); SCNetworkServiceRef service; - CFStringRef serviceID; bsdName = SCNetworkInterfaceGetBSDName(interface); // create network service - service = SCNetworkServiceCreate(prefs, interface); + service = _SCNetworkServiceCreatePreconfigured(prefs, interface); if (service == NULL) { - SC_log(LOG_ERR, "could not create network service for \"%@\": %s", - bsdName, - SCErrorString(SCError())); - continue; - } - - // update network service to use a consistent serviceID - serviceID = copyInterfaceUUID(bsdName); - if (serviceID != NULL) { - ok = _SCNetworkServiceSetServiceID(service, serviceID); - CFRelease(serviceID); - if (!ok) { - SC_log(LOG_ERR, "_SCNetworkServiceSetServiceID() failed: %s", - SCErrorString(SCError())); - // ... and keep whatever random UUID was created for the service - } - } else { - SC_log(LOG_ERR, "could not create serviceID for \"%@\"", bsdName); - // ... and we'll use whatever random UUID was created for the service - } - - // establish [template] configuration - ok = SCNetworkServiceEstablishDefaultConfiguration(service); - if (!ok) { - SC_log(LOG_ERR, "could not establish network service for \"%@\": %s", - bsdName, - SCErrorString(SCError())); - SCNetworkServiceRemove(service); - CFRelease(service); continue; } @@ -1057,13 +945,6 @@ updateConfiguration(SCPreferencesRef prefs, void *info) { #pragma unused(info) - os_activity_t activity; - - activity = os_activity_create("processing [SC] preferences.plist changes", - OS_ACTIVITY_CURRENT, - OS_ACTIVITY_FLAG_DEFAULT); - os_activity_scope(activity); - #if !TARGET_OS_IPHONE if ((notificationType & kSCPreferencesNotificationCommit) == kSCPreferencesNotificationCommit) { SCNetworkSetRef current; @@ -1086,6 +967,9 @@ updateConfiguration(SCPreferencesRef prefs, /* add any [Apple] pre-configured network services */ updatePreConfiguredConfiguration(prefs); + /* remove any excluded network services */ + excludeConfigurations(prefs); + /* update SCDynamicStore (Setup:) */ updateSCDynamicStore(prefs); @@ -1096,8 +980,6 @@ updateConfiguration(SCPreferencesRef prefs, done : - os_release(activity); - return; } @@ -1115,6 +997,13 @@ prime_PreferencesMonitor() } +#ifndef MAIN +#define PREFERENCES_MONITOR_PLIST NULL +#else // !MAIN +#define PREFERENCES_MONITOR_PLIST CFSTR("/tmp/preferences.plist") +#endif // !MAIN + + __private_extern__ void load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose) @@ -1135,27 +1024,34 @@ load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose) } /* open a SCPreferences session */ -#ifndef MAIN - prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL); -#else // !MAIN - prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), CFSTR("/tmp/preferences.plist")); -#endif // !MAIN + prefs = SCPreferencesCreateWithOptions(NULL, + MY_PLUGIN_ID, + PREFERENCES_MONITOR_PLIST, + NULL, // authorization + NULL); if (prefs != NULL) { Boolean need_update = FALSE; - CFStringRef new_model; + CFStringRef new_model; + CFStringRef old_model; + + // check if we need to update the configuration + __SCNetworkConfigurationUpgrade(&prefs, NULL, TRUE); + // check if we need to regenerate the configuration for a new model + old_model = SCPreferencesGetValue(prefs, MODEL); new_model = _SC_hw_model(FALSE); + if ((old_model != NULL) && !_SC_CFEqual(old_model, new_model)) { + SC_log(LOG_NOTICE, "Hardware model changed\n" + " created on \"%@\"\n" + " now on \"%@\"", + old_model, + new_model); - /* Need to regenerate the new configuration for new model */ - if (new_model != NULL) { - CFStringRef old_model; + // save (and clean) the configuration that was created for "other" hardware + savePastConfiguration(old_model); - old_model = SCPreferencesGetValue(prefs, MODEL); - if (old_model != NULL && !_SC_CFEqual(old_model, new_model)) { - // if new hardware - need_update = TRUE; - restorePrefs = previousConfigurationAvailable(); - } + // ... and we'll update the configuration later (when the IORegistry quiesces) + need_update = TRUE; } if (!need_update) { @@ -1211,7 +1107,7 @@ load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose) int main(int argc, char **argv) { - _sc_log = FALSE; + _sc_log = kSCLogDestinationFile; _sc_verbose = (argc > 1) ? TRUE : FALSE; load_PreferencesMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);