SCNetworkConfigurationInternal.c [plain text]
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCValidation.h>
#include <SystemConfiguration/SCPrivate.h>
#include <sys/ioctl.h>
#include <net/if.h>
__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 :
config = NULL;
break;
case 1 :
if (CFDictionaryContainsKey(config, kSCResvInactive)) {
config = NULL;
}
break;
default :
break;
}
return config;
}
__private_extern__ Boolean
__setPrefsConfiguration(SCPreferencesRef prefs,
CFStringRef path,
CFDictionaryRef config,
Boolean keepInactive)
{
CFMutableDictionaryRef newConfig = NULL;
Boolean ok;
if ((config != NULL) && !isA_CFDictionary(config)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
if (config != NULL) {
newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
}
if (keepInactive) {
CFDictionaryRef curConfig;
if (config == NULL) {
newConfig = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
curConfig = SCPreferencesPathGetValue(prefs, path);
if (isA_CFDictionary(curConfig) && CFDictionaryContainsKey(curConfig, kSCResvInactive)) {
CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
} else {
CFDictionaryRemoveValue(newConfig, kSCResvInactive);
}
}
if (newConfig != NULL) {
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;
curConfig = SCPreferencesPathGetValue(prefs, path);
if (curConfig != NULL) {
if (!isA_CFDictionary(curConfig)) {
_SCErrorSet(kSCStatusFailed);
return FALSE;
}
newConfig = CFDictionaryCreateMutableCopy(NULL, 0, curConfig);
if (enabled) {
CFDictionaryRemoveValue(newConfig, kSCResvInactive);
} else {
CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
}
} else {
if (!enabled) {
newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
}
}
if (newConfig != NULL) {
ok = SCPreferencesPathSetValue(prefs, path, newConfig);
CFRelease(newConfig);
} else {
ok = SCPreferencesPathRemoveValue(prefs, path);
if (!ok && (SCError() == kSCStatusNoKey)) {
ok = TRUE;
}
}
return ok;
}
static CFDictionaryRef
__copyTemplates()
{
CFBundleRef bundle;
Boolean ok;
CFDictionaryRef templates;
CFURLRef url;
CFStringRef xmlError = NULL;
CFDataRef xmlTemplates = NULL;
bundle = _SC_CFBundleGet();
if (bundle == NULL) {
return NULL;
}
url = CFBundleCopyResourceURL(bundle, CFSTR("NetworkConfiguration"), CFSTR("plist"), NULL);
if (url == NULL) {
return NULL;
}
ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlTemplates, NULL, NULL, NULL);
CFRelease(url);
if (!ok || (xmlTemplates == NULL)) {
return NULL;
}
templates = CFPropertyListCreateFromXMLData(NULL, xmlTemplates, kCFPropertyListImmutable, &xmlError);
CFRelease(xmlTemplates);
if (templates == NULL) {
if (xmlError != NULL) {
SCLog(TRUE, LOG_DEBUG, CFSTR("could not load SCNetworkConfiguration templates: %@"), xmlError);
CFRelease(xmlError);
}
return NULL;
}
if (!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;
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;
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;
bzero(&ifr, sizeof(ifr));
(void) _SC_cfstring_to_cstring(interface,
ifr.ifr_name,
sizeof(ifr.ifr_name),
kCFStringEncodingASCII);
if (ioctl(s, SIOCIFCREATE, &ifr) == -1) {
SCLog(TRUE,
LOG_ERR,
CFSTR("could not create interface \"%@\": %s"),
interface,
strerror(errno));
return FALSE;
}
return TRUE;
}
__private_extern__ Boolean
__destroyInterface(int s, CFStringRef interface)
{
struct ifreq ifr;
bzero(&ifr, sizeof(ifr));
(void) _SC_cfstring_to_cstring(interface,
ifr.ifr_name,
sizeof(ifr.ifr_name),
kCFStringEncodingASCII);
if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) {
SCLog(TRUE,
LOG_ERR,
CFSTR("could not destroy interface \"%@\": %s"),
interface,
strerror(errno));
return FALSE;
}
return 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) {
CFRelease(path);
return NULL;
}
dict = CFDictionaryCreate(NULL,
NULL, NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
ok = SCPreferencesPathSetValue(prefs, path, dict);
CFRelease(dict);
if (!ok) {
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)) {
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;
if (config != NULL) {
encryption = CFDictionaryGetValue(config, encryptionKey);
}
if ((encryption == NULL) ||
(isA_CFString(encryption) &&
CFEqual(encryption, encryptionKeyChainValue))) {
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);
}
}
}
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;
}