Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
17 kB · 673 lines
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674/* * Copyright (c) 2004-2007, 2009, 2010-2013, 2015-2018 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, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * 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@ */
/* * Modification History * * May 27, 2004 Allan Nathanson <ajn@apple.com> * - initial revision */
#include "SCPreferencesInternal.h"#include "SCNetworkConfigurationInternal.h"
#include <sys/ioctl.h>#include <net/if.h>
__private_extern__ os_log_t__log_SCNetworkConfiguration(void){ static os_log_t log = NULL;
if (log == NULL) { log = os_log_create("com.apple.SystemConfiguration", "SCNetworkConfiguration"); }
return log;}
__private_extern__ CFDictionaryRef__getPrefsConfiguration(SCPreferencesRef prefs, CFStringRef path){ CFDictionaryRef config; CFIndex n;
config = SCPreferencesPathGetValue(prefs, path);
n = isA_CFDictionary(config) ? CFDictionaryGetCount(config) : 0; switch (n) { case 0 : // ignore empty configuration entities config = NULL; break; case 1 : if (CFDictionaryContainsKey(config, kSCResvInactive)) { // ignore [effectively] empty configuration entities config = NULL; } break; default : break; }
return config;}
__private_extern__ Boolean__setPrefsConfiguration(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef config, Boolean keepInactive){ CFDictionaryRef curConfig; CFMutableDictionaryRef newConfig = NULL; Boolean ok;
if ((config != NULL) && !isA_CFDictionary(config)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
curConfig = SCPreferencesPathGetValue(prefs, path);
if (config != NULL) { newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); }
if (keepInactive) { if (config == NULL) { newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); }
if (isA_CFDictionary(curConfig) && CFDictionaryContainsKey(curConfig, kSCResvInactive)) { // if currently disabled CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue); } else { // if currently enabled CFDictionaryRemoveValue(newConfig, kSCResvInactive); } }
// set new configuration if (_SC_CFEqual(curConfig, newConfig)) { // if no change if (newConfig != NULL) CFRelease(newConfig); ok = TRUE; } else if (newConfig != NULL) { // if new configuration (or we are preserving a disabled state) ok = SCPreferencesPathSetValue(prefs, path, newConfig); CFRelease(newConfig); } else { ok = SCPreferencesPathRemoveValue(prefs, path); if (!ok && (SCError() == kSCStatusNoKey)) { ok = TRUE; } }
return ok;}
__private_extern__ Boolean__getPrefsEnabled(SCPreferencesRef prefs, CFStringRef path){ CFDictionaryRef config;
config = SCPreferencesPathGetValue(prefs, path); if (isA_CFDictionary(config) && CFDictionaryContainsKey(config, kSCResvInactive)) { return FALSE; }
return TRUE;}
__private_extern__ Boolean__setPrefsEnabled(SCPreferencesRef prefs, CFStringRef path, Boolean enabled){ CFDictionaryRef curConfig; CFMutableDictionaryRef newConfig = NULL; Boolean ok = FALSE;
// preserve current configuration curConfig = SCPreferencesPathGetValue(prefs, path); if (curConfig != NULL) { if (!isA_CFDictionary(curConfig)) { _SCErrorSet(kSCStatusFailed); return FALSE; } newConfig = CFDictionaryCreateMutableCopy(NULL, 0, curConfig);
if (enabled) { // enable CFDictionaryRemoveValue(newConfig, kSCResvInactive); } else { // disable CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue); } } else { if (!enabled) { // disable newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue); } }
// set new configuration if (_SC_CFEqual(curConfig, newConfig)) { // if no change if (newConfig != NULL) CFRelease(newConfig); ok = TRUE; } else if (newConfig != NULL) { // if updated configuration (or we are establishing as disabled) ok = SCPreferencesPathSetValue(prefs, path, newConfig); CFRelease(newConfig); } else { ok = SCPreferencesPathRemoveValue(prefs, path); if (!ok && (SCError() == kSCStatusNoKey)) { ok = TRUE; } }
return ok;}
#if TARGET_OS_OSX#define SYSTEMCONFIGURATION_RESOURCES_PATH SYSTEMCONFIGURATION_FRAMEWORK_PATH "/Resources"#else#define SYSTEMCONFIGURATION_RESOURCES_PATH SYSTEMCONFIGURATION_FRAMEWORK_PATH#endif // TARGET_OS_OSX
#define NETWORKCONFIGURATION_RESOURCE_FILE "NetworkConfiguration.plist"
static CFDictionaryRef__copyTemplates(){ CFBundleRef bundle; CFDictionaryRef templates; CFURLRef url;
bundle = _SC_CFBundleGet(); if (bundle == NULL) { return NULL; }
url = CFBundleCopyResourceURL(bundle, CFSTR("NetworkConfiguration"), CFSTR("plist"), NULL); if (url == NULL) { SC_log(LOG_ERR, "failed to GET resource URL to \"%s\". Trying harder...", NETWORKCONFIGURATION_RESOURCE_FILE); url = CFURLCreateWithFileSystemPath(NULL, CFSTR(SYSTEMCONFIGURATION_RESOURCES_PATH "/" NETWORKCONFIGURATION_RESOURCE_FILE), kCFURLPOSIXPathStyle, TRUE);
if (url == NULL) { SC_log(LOG_ERR, "failed to CREATE resource URL to \"%s\"", SYSTEMCONFIGURATION_RESOURCES_PATH "/" NETWORKCONFIGURATION_RESOURCE_FILE); return NULL; } }
templates = _SCCreatePropertyListFromResource(url); CFRelease(url);
if ((templates != NULL) && !isA_CFDictionary(templates)) { CFRelease(templates); return NULL; }
return templates;}
__private_extern__ CFDictionaryRef__copyInterfaceTemplate(CFStringRef interfaceType, CFStringRef childInterfaceType){ CFDictionaryRef interface = NULL; CFDictionaryRef interfaces; CFDictionaryRef templates;
templates = __copyTemplates(); if (templates == NULL) { return NULL; }
interfaces = CFDictionaryGetValue(templates, CFSTR("Interface")); if (!isA_CFDictionary(interfaces)) { CFRelease(templates); return NULL; }
if (childInterfaceType == NULL) { interface = CFDictionaryGetValue(interfaces, interfaceType); } else { CFStringRef expandedType;
if (CFStringFind(childInterfaceType, CFSTR("."), 0).location != kCFNotFound) { // if "vendor" type childInterfaceType = CFSTR("*"); }
expandedType = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-%@"), interfaceType, childInterfaceType); interface = CFDictionaryGetValue(interfaces, expandedType); CFRelease(expandedType); }
if (isA_CFDictionary(interface) && (CFDictionaryGetCount(interface) > 0)) { CFRetain(interface); } else { interface = NULL; }
CFRelease(templates);
return interface;}
__private_extern__ CFDictionaryRef__copyProtocolTemplate(CFStringRef interfaceType, CFStringRef childInterfaceType, CFStringRef protocolType){ CFDictionaryRef interface = NULL; CFDictionaryRef protocol = NULL; CFDictionaryRef protocols; CFDictionaryRef templates;
templates = __copyTemplates(); if (templates == NULL) { return NULL; }
protocols = CFDictionaryGetValue(templates, CFSTR("Protocol")); if (!isA_CFDictionary(protocols)) { CFRelease(templates); return NULL; }
if (childInterfaceType == NULL) { interface = CFDictionaryGetValue(protocols, interfaceType); } else { CFStringRef expandedType;
if (CFStringFind(childInterfaceType, CFSTR("."), 0).location != kCFNotFound) { // if "vendor" type childInterfaceType = CFSTR("*"); }
expandedType = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-%@"), interfaceType, childInterfaceType); interface = CFDictionaryGetValue(protocols, expandedType); CFRelease(expandedType); }
if (isA_CFDictionary(interface)) { protocol = CFDictionaryGetValue(interface, protocolType); if (isA_CFDictionary(protocol)) { CFRetain(protocol); } else { protocol = NULL; } }
CFRelease(templates);
return protocol;}
__private_extern__ Boolean__createInterface(int s, CFStringRef interface){ struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); (void) _SC_cfstring_to_cstring(interface, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII);
if (ioctl(s, SIOCIFCREATE, &ifr) == -1) { SC_log(LOG_NOTICE, "could not create interface \"%@\": %s", interface, strerror(errno)); return FALSE; }
return TRUE;}
__private_extern__ Boolean__destroyInterface(int s, CFStringRef interface){ struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); (void) _SC_cfstring_to_cstring(interface, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII);
if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) { SC_log(LOG_NOTICE, "could not destroy interface \"%@\": %s", interface, strerror(errno)); return FALSE; }
return TRUE;}
/* * For rdar://problem/4685223 * * To keep MoreSCF happy we need to ensure that the first "Set" and * "NetworkService" have a [less than] unique identifier that can * be parsed as a numeric string. * * Note: this backwards compatibility code must be enabled using the * following command: * * sudo defaults write \ * /Library/Preferences/SystemConfiguration/preferences \ * MoreSCF \ * -bool true */__private_extern__CFStringRef__SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(SCPreferencesRef prefs, CFStringRef prefix){ static int hack = -1; CFStringRef path = NULL;
if (hack < 0) { CFBooleanRef enable;
enable = SCPreferencesGetValue(prefs, CFSTR("MoreSCF")); hack = (isA_CFBoolean(enable) && CFBooleanGetValue(enable)) ? 1 : 0; }
if (hack > 0) { CFDictionaryRef dict; Boolean ok;
path = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), prefix, CFSTR("0")); dict = SCPreferencesPathGetValue(prefs, path); if (dict != NULL) { // if path "0" exists CFRelease(path); return NULL; }
// unique child with path "0" does not exist, create dict = CFDictionaryCreate(NULL, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok = SCPreferencesPathSetValue(prefs, path, dict); CFRelease(dict); if (!ok) { // if create failed CFRelease(path); return NULL; } }
return path;}
static CFDataRef__copy_legacy_password(CFTypeRef password){ if (password == NULL) { return NULL; }
if (isA_CFData(password)) { CFIndex n;
n = CFDataGetLength(password); if ((n % sizeof(UniChar)) == 0) { CFStringEncoding encoding; CFStringRef str;
#if __BIG_ENDIAN__ encoding = (*(CFDataGetBytePtr(password) + 1) == 0x00) ? kCFStringEncodingUTF16LE : kCFStringEncodingUTF16BE;#else // __LITTLE_ENDIAN__ encoding = (*(CFDataGetBytePtr(password) ) == 0x00) ? kCFStringEncodingUTF16BE : kCFStringEncodingUTF16LE;#endif str = CFStringCreateWithBytes(NULL, (const UInt8 *)CFDataGetBytePtr(password), n, encoding, FALSE); password = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0); CFRelease(str); } else { password = NULL; } } else if (isA_CFString(password) && (CFStringGetLength(password) > 0)) { // convert password to CFData password = CFStringCreateExternalRepresentation(NULL, password, kCFStringEncodingUTF8, 0); } else { password = NULL; }
return password;}
__private_extern__Boolean__extract_password(SCPreferencesRef prefs, CFDictionaryRef config, CFStringRef passwordKey, CFStringRef encryptionKey, CFStringRef encryptionKeyChainValue, CFStringRef unique_id, CFDataRef *password){ CFStringRef encryption = NULL; Boolean exists = FALSE;
// check for keychain password if (config != NULL) { encryption = CFDictionaryGetValue(config, encryptionKey); } if ((encryption == NULL) || (isA_CFString(encryption) && CFEqual(encryption, encryptionKeyChainValue))) { // check password if (password != NULL) { if (prefs != NULL) { *password = _SCPreferencesSystemKeychainPasswordItemCopy(prefs, unique_id); } else { *password = _SCSecKeychainPasswordItemCopy(NULL, unique_id); } exists = (*password != NULL); } else { if (prefs != NULL) { exists = _SCPreferencesSystemKeychainPasswordItemExists(prefs, unique_id); } else { exists = _SCSecKeychainPasswordItemExists(NULL, unique_id); } } }
// as needed, check for in-line password if (!exists && (encryption == NULL) && (config != NULL)) { CFDataRef inline_password;
inline_password = CFDictionaryGetValue(config, passwordKey); inline_password = __copy_legacy_password(inline_password); if (inline_password != NULL) { exists = TRUE;
if (password != NULL) { *password = inline_password; } else { CFRelease(inline_password); } } }
return exists;}
__private_extern__Boolean__remove_password(SCPreferencesRef prefs, CFDictionaryRef config, CFStringRef passwordKey, CFStringRef encryptionKey, CFStringRef encryptionKeyChainValue, CFStringRef unique_id, CFDictionaryRef *newConfig){ CFStringRef encryption = NULL; Boolean ok = FALSE;
// check for keychain password if (config != NULL) { encryption = CFDictionaryGetValue(config, encryptionKey); } if ((encryption == NULL) || (isA_CFString(encryption) && CFEqual(encryption, encryptionKeyChainValue))) { // remove keychain password if (prefs != NULL) { ok = _SCPreferencesSystemKeychainPasswordItemRemove(prefs, unique_id); } else { ok = _SCSecKeychainPasswordItemRemove(NULL, unique_id); } }
// as needed, check if we have an in-line password that we can remove if (!ok && (encryption == NULL) && (config != NULL)) { CFDataRef inline_password;
inline_password = CFDictionaryGetValue(config, passwordKey); inline_password = __copy_legacy_password(inline_password); if (inline_password != NULL) { CFRelease(inline_password); ok = TRUE; } }
if (newConfig != NULL) { if (ok && (config != NULL)) { CFMutableDictionaryRef temp;
temp = CFDictionaryCreateMutableCopy(NULL, 0, config); CFDictionaryRemoveValue(temp, passwordKey); CFDictionaryRemoveValue(temp, encryptionKey); *newConfig = (CFDictionaryRef)temp; } else { *newConfig = NULL; } }
return ok;}
__private_extern__ Boolean__rank_to_str(SCNetworkServicePrimaryRank rank, CFStringRef *rankStr){ switch (rank) { case kSCNetworkServicePrimaryRankDefault : *rankStr = NULL; break; case kSCNetworkServicePrimaryRankFirst : *rankStr = kSCValNetServicePrimaryRankFirst; break; case kSCNetworkServicePrimaryRankLast : *rankStr = kSCValNetServicePrimaryRankLast; break; case kSCNetworkServicePrimaryRankNever : *rankStr = kSCValNetServicePrimaryRankNever; break; case kSCNetworkServicePrimaryRankScoped : *rankStr = kSCValNetServicePrimaryRankScoped; break; default : return FALSE; }
return TRUE;}
__private_extern__ Boolean__str_to_rank(CFStringRef rankStr, SCNetworkServicePrimaryRank *rank){ if (isA_CFString(rankStr)) { if (CFEqual(rankStr, kSCValNetServicePrimaryRankFirst)) { *rank = kSCNetworkServicePrimaryRankFirst; } else if (CFEqual(rankStr, kSCValNetServicePrimaryRankLast)) { *rank = kSCNetworkServicePrimaryRankLast; } else if (CFEqual(rankStr, kSCValNetServicePrimaryRankNever)) { *rank = kSCNetworkServicePrimaryRankNever; } else if (CFEqual(rankStr, kSCValNetServicePrimaryRankScoped)) { *rank = kSCNetworkServicePrimaryRankScoped; } else { return FALSE; } } else if (rankStr == NULL) { *rank = kSCNetworkServicePrimaryRankDefault; } else { return FALSE; }
return TRUE;}