EAPOLClientConfiguration.c [plain text]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <TargetConditionals.h>
#include <CoreFoundation/CFString.h>
#include <SystemConfiguration/SCNetworkConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
#include <notify.h>
#include <pthread.h>
#include "EAP.h"
#include "EAPClientProperties.h"
#include "EAPOLControlTypes.h"
#include "EAPOLClientConfigurationInternal.h"
#include "symbol_scope.h"
#include "myCFUtil.h"
#define kPrefsName CFSTR("EAPOLClientConfiguration")
const char * kEAPOLClientConfigurationChangedNotifyKey = "com.apple.network.eapolclientconfiguration";
#define kConfigurationKeyProfiles CFSTR("Profiles")
#define kConfigurationKeyDefaultAuthenticationProperties CFSTR("DefaultAuthenticationProperties")
#define kEAPOL CFSTR("EAPOL")
#define kSystemProfileID CFSTR("SystemProfileID")
#define kLoginWindowProfileIDs CFSTR("LoginWindowProfileIDs")
const CFStringRef kEAPOLClientProfileWLANSecurityTypeWEP = CFSTR("WEP");
const CFStringRef kEAPOLClientProfileWLANSecurityTypeWPA = CFSTR("WPA");
const CFStringRef kEAPOLClientProfileWLANSecurityTypeWPA2 = CFSTR("WPA2");
const CFStringRef kEAPOLClientProfileWLANSecurityTypeAny = CFSTR("Any");
STATIC SCPreferencesRef
get_sc_prefs(EAPOLClientConfigurationRef cfg)
{
if (cfg->sc_prefs == NULL) {
cfg->sc_prefs = SCPreferencesCreate(NULL, kPrefsName, NULL);
if (cfg->sc_prefs == NULL) {
syslog(LOG_NOTICE,
"EAPOLClientConfiguration: SCPreferencesCreate failed, %s",
SCErrorString(SCError()));
}
}
return (cfg->sc_prefs);
}
STATIC CFArrayRef
copy_configured_interface_names(SCPreferencesRef prefs, CFStringRef entity_name)
{
SCNetworkSetRef current_set = NULL;
int count;
int i;
CFMutableArrayRef ret_names = NULL;
CFRange ret_names_range = { 0 , 0 };
CFArrayRef services = NULL;
if (prefs == NULL) {
goto done;
}
current_set = SCNetworkSetCopyCurrent(prefs);
if (current_set == NULL) {
goto done;
}
services = SCNetworkSetCopyServices(current_set);
if (services == NULL) {
goto done;
}
count = CFArrayGetCount(services);
for (i = 0; i < count; i++) {
CFStringRef this_if_name;
SCNetworkInterfaceRef this_if;
SCNetworkServiceRef s;
s = (SCNetworkServiceRef)CFArrayGetValueAtIndex(services, i);
this_if = SCNetworkServiceGetInterface(s);
if (this_if == NULL) {
continue;
}
if (entity_name != NULL
&& (SCNetworkInterfaceGetExtendedConfiguration(this_if, entity_name)
== NULL)) {
continue;
}
this_if_name = SCNetworkInterfaceGetBSDName(this_if);
if (this_if_name == NULL) {
continue;
}
if (ret_names == NULL
|| CFArrayContainsValue(ret_names, ret_names_range,
this_if_name) == FALSE) {
if (ret_names == NULL) {
ret_names = CFArrayCreateMutable(NULL, count,
&kCFTypeArrayCallBacks);
}
CFArrayAppendValue(ret_names, this_if_name);
ret_names_range.length++;
}
}
done:
my_CFRelease(¤t_set);
my_CFRelease(&services);
return (ret_names);
}
STATIC CFDictionaryRef
copy_profiles_for_mode(EAPOLClientConfigurationRef cfg,
EAPOLControlMode mode)
{
CFArrayRef all_names;
int count;
int i;
CFMutableDictionaryRef ret_profiles = NULL;
switch (mode) {
case kEAPOLControlModeLoginWindow:
case kEAPOLControlModeSystem:
break;
default:
return (NULL);
}
all_names = copy_configured_interface_names(get_sc_prefs(cfg), kEAPOL);
if (all_names == NULL) {
return (NULL);
}
count = CFArrayGetCount(all_names);
for (i = 0; i < count; i++) {
CFStringRef if_name = CFArrayGetValueAtIndex(all_names, i);
CFTypeRef val = NULL;
if (mode == kEAPOLControlModeSystem) {
EAPOLClientProfileRef profile;
profile = EAPOLClientConfigurationGetSystemProfile(cfg, if_name);
if (profile != NULL) {
val = profile;
CFRetain(val);
}
}
else {
CFArrayRef profiles;
profiles
= EAPOLClientConfigurationCopyLoginWindowProfiles(cfg,
if_name);
if (profiles != NULL) {
val = profiles;
}
}
if (val != NULL) {
if (ret_profiles == NULL) {
ret_profiles
= CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
CFDictionarySetValue(ret_profiles, if_name, val);
CFRelease(val);
}
}
CFRelease(all_names);
return (ret_profiles);
}
STATIC SCNetworkInterfaceRef
copy_configured_interface(SCPreferencesRef prefs, CFStringRef if_name)
{
SCNetworkSetRef current_set = NULL;
int count;
int i;
SCNetworkInterfaceRef ret_if = NULL;
CFArrayRef services = NULL;
current_set = SCNetworkSetCopyCurrent(prefs);
if (current_set == NULL) {
goto done;
}
services = SCNetworkSetCopyServices(current_set);
if (services == NULL) {
goto done;
}
count = CFArrayGetCount(services);
for (i = 0; i < count; i++) {
CFStringRef this_if_name;
SCNetworkInterfaceRef this_if;
SCNetworkServiceRef s;
s = (SCNetworkServiceRef)CFArrayGetValueAtIndex(services, i);
this_if = SCNetworkServiceGetInterface(s);
if (this_if == NULL) {
continue;
}
this_if_name = SCNetworkInterfaceGetBSDName(this_if);
if (this_if_name == NULL) {
continue;
}
if (CFEqual(this_if_name, if_name)) {
ret_if = this_if;
CFRetain(ret_if);
break;
}
}
done:
my_CFRelease(¤t_set);
my_CFRelease(&services);
return (ret_if);
}
STATIC SCNetworkInterfaceRef
copy_present_interface(CFStringRef if_name)
{
int count = 0;
int i;
CFArrayRef list;
SCNetworkInterfaceRef ret = NULL;
list = SCNetworkInterfaceCopyAll();
if (list != NULL) {
count = CFArrayGetCount(list);
}
if (count == 0) {
goto done;
}
for (i = 0; i < count; i++) {
SCNetworkInterfaceRef this_if;
CFStringRef this_if_name;
this_if = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(list, i);
this_if_name = SCNetworkInterfaceGetBSDName(this_if);
if (this_if_name == NULL) {
continue;
}
if (CFEqual(if_name, this_if_name)) {
ret = this_if;
CFRetain(ret);
break;
}
}
done:
my_CFRelease(&list);
return (ret);
}
STATIC void
import_profiles(EAPOLClientConfigurationRef cfg)
{
int count = 0;
int i;
const void * * keys;
CFDictionaryRef prefs_dict;
CFMutableDictionaryRef profiles_dict;
CFMutableDictionaryRef ssids_dict;
const void * * values;
profiles_dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
ssids_dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
prefs_dict = SCPreferencesGetValue(cfg->eap_prefs,
kConfigurationKeyProfiles);
if (isA_CFDictionary(prefs_dict) != NULL) {
count = CFDictionaryGetCount(prefs_dict);
}
if (count == 0) {
goto done;
}
keys = (const void * *)malloc(sizeof(*keys) * count * 2);
values = keys + count;
CFDictionaryGetKeysAndValues(prefs_dict, keys, values);
for (i = 0; i < count; i++) {
EAPOLClientProfileRef profile;
CFDictionaryRef profile_dict = values[i];
CFStringRef profileID = keys[i];
CFDataRef ssid;
if (isA_CFDictionary(profile_dict) == NULL) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: invalid profile with id %@"),
profileID);
continue;
}
profile = EAPOLClientProfileCreateWithDictAndProfileID(profile_dict,
profileID);
if (profile == NULL) {
continue;
}
ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(profile, NULL);
if (ssid != NULL) {
CFStringRef conflicting_profileID;
conflicting_profileID = CFDictionaryGetValue(ssids_dict, ssid);
if (conflicting_profileID != NULL) {
CFStringRef ssid_str = my_CFStringCreateWithData(ssid);
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: ignoring profile %@: "
"SSID '%@' already used by %@"),
profileID, ssid_str, conflicting_profileID);
CFRelease(ssid_str);
CFRelease(profile);
continue;
}
CFDictionarySetValue(ssids_dict, ssid, profileID);
}
CFDictionarySetValue(profiles_dict, profileID, profile);
EAPOLClientProfileSetConfiguration(profile, cfg);
CFRelease(profile);
}
free(keys);
done:
cfg->ssids = ssids_dict;
cfg->profiles = profiles_dict;
return;
}
STATIC CFDictionaryRef
export_profiles(EAPOLClientConfigurationRef cfg)
{
int count;
CFMutableDictionaryRef dict;
int i;
const void * * values;
count = CFDictionaryGetCount(cfg->profiles);
dict = CFDictionaryCreateMutable(NULL, count,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (count == 0) {
goto done;
}
values = (const void * *)malloc(sizeof(*values) * count);
CFDictionaryGetKeysAndValues(cfg->profiles, NULL, values);
for (i = 0; i < count; i++) {
EAPOLClientProfileRef profile = (EAPOLClientProfileRef)values[i];
CFDictionaryRef profile_dict;
CFStringRef profileID;
profile_dict
= EAPOLClientProfileCreateDictAndProfileID(profile, &profileID);
if (profile_dict == NULL) {
my_CFRelease(&dict);
break;
}
CFDictionarySetValue(dict, profileID, profile_dict);
CFRelease(profile_dict);
CFRelease(profileID);
}
free(values);
done:
return (dict);
}
STATIC CFArrayRef
myCFArrayCreateWithIntegerList(const int * list, int list_count)
{
CFMutableArrayRef array;
int i;
array = CFArrayCreateMutable(NULL, list_count, &kCFTypeArrayCallBacks);
for (i = 0; i < list_count; i++) {
CFNumberRef num;
num = CFNumberCreate(NULL, kCFNumberIntType, list + i);
CFArrayAppendValue(array, num);
CFRelease(num);
}
return (array);
}
STATIC CFDictionaryRef
copy_def_auth_props(SCPreferencesRef eap_prefs)
{
CFArrayRef accept_types = NULL;
CFMutableDictionaryRef auth_props;
int list[] = {
kEAPTypePEAP,
kEAPTypeTTLS,
kEAPTypeCiscoLEAP,
kEAPTypeEAPFAST,
kEAPTypeTLS
};
int list_count = sizeof(list) / sizeof(list[0]);
CFDictionaryRef pref_auth_props;
pref_auth_props
= SCPreferencesGetValue(eap_prefs,
kConfigurationKeyDefaultAuthenticationProperties);
if (pref_auth_props != NULL) {
accept_types = CFDictionaryGetValue(pref_auth_props,
kEAPClientPropAcceptEAPTypes);
if (accept_types_valid(accept_types)) {
CFRetain(pref_auth_props);
return (pref_auth_props);
}
if (accept_types != NULL) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: default Authentication "
"Properties invalid, %@ - ignoring"), pref_auth_props);
}
}
accept_types = myCFArrayCreateWithIntegerList(list, list_count);
auth_props = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(auth_props,
kEAPClientPropAcceptEAPTypes,
accept_types);
CFDictionarySetValue(auth_props, kEAPClientPropEAPFASTUsePAC,
kCFBooleanTrue);
CFDictionarySetValue(auth_props, kEAPClientPropEAPFASTProvisionPAC,
kCFBooleanTrue);
CFRelease(accept_types);
return (auth_props);
}
STATIC SCNetworkServiceRef
copy_service(SCPreferencesRef prefs, SCNetworkInterfaceRef net_if)
{
int count = 0;
int i;
SCNetworkServiceRef service = NULL;
CFArrayRef list;
list = SCNetworkServiceCopyAll(prefs);
if (list != NULL) {
count = CFArrayGetCount(list);
}
if (count == 0) {
goto done;
}
for (i = 0; i < count; i++) {
SCNetworkInterfaceRef this_if;
SCNetworkServiceRef this_service;
this_service = (SCNetworkServiceRef)CFArrayGetValueAtIndex(list, i);
this_if = SCNetworkServiceGetInterface(this_service);
if (this_if == NULL) {
continue;
}
if (CFEqual(this_if, net_if)) {
service = this_service;
CFRetain(service);
break;
}
}
done:
my_CFRelease(&list);
return (service);
}
STATIC SCNetworkInterfaceRef
copy_interface(SCPreferencesRef prefs, CFStringRef if_name,
SCNetworkSetRef * ret_set_p,
SCNetworkServiceRef * ret_service_p)
{
SCNetworkSetRef current_set = NULL;
SCNetworkServiceRef service = NULL;
SCNetworkInterfaceRef net_if;
SCNetworkInterfaceRef ret = NULL;
net_if = copy_configured_interface(prefs, if_name);
if (net_if != NULL) {
ret = net_if;
CFRetain(ret);
goto done;
}
net_if = copy_present_interface(if_name);
if (net_if == NULL) {
goto done;
}
service = copy_service(prefs, net_if);
if (service == NULL) {
syslog(LOG_ERR,
"EAPOLClientConfiguration: can't get service");
goto done;
}
current_set = SCNetworkSetCopyCurrent(prefs);
if (current_set == NULL) {
syslog(LOG_ERR,
"EAPOLClientConfiguration: can't get current set");
goto done;
}
if (SCNetworkSetAddService(current_set, service) == FALSE) {
syslog(LOG_ERR,
"EAPOLClientConfiguration: failed to add dummy service");
goto done;
}
ret = SCNetworkServiceGetInterface(service);
CFRetain(ret);
done:
my_CFRelease(&net_if);
if (ret == NULL) {
my_CFRelease(&service);
my_CFRelease(¤t_set);
}
*ret_service_p = service;
*ret_set_p = current_set;
return (ret);
}
STATIC Boolean
set_eapol_configuration(SCPreferencesRef prefs, CFStringRef if_name,
CFDictionaryRef dict)
{
SCNetworkSetRef current_set = NULL;
SCNetworkInterfaceRef net_if_save;
Boolean ret = FALSE;
SCNetworkServiceRef service = NULL;
net_if_save = copy_interface(prefs, if_name, ¤t_set, &service);
if (net_if_save != NULL) {
ret = SCNetworkInterfaceSetExtendedConfiguration(net_if_save, kEAPOL,
dict);
if (ret == FALSE) {
syslog(LOG_ERR,
"EAPOLClientConfiguration: SetExtendedConfiguration failed");
}
}
if (current_set != NULL) {
SCNetworkSetRemoveService(current_set, service);
CFRelease(current_set);
}
my_CFRelease(&service);
my_CFRelease(&net_if_save);
return (ret);
}
STATIC CFDictionaryRef
get_eapol_configuration(SCPreferencesRef prefs, CFStringRef if_name,
SCNetworkInterfaceRef * ret_net_if)
{
SCNetworkSetRef current_set = NULL;
CFDictionaryRef dict = NULL;
SCNetworkServiceRef service = NULL;
SCNetworkInterfaceRef net_if = NULL;
net_if = copy_interface(prefs, if_name, ¤t_set, &service);
if (net_if != NULL) {
dict = SCNetworkInterfaceGetExtendedConfiguration(net_if, kEAPOL);
}
my_CFRelease(¤t_set);
my_CFRelease(&service);
if (ret_net_if != NULL) {
*ret_net_if = net_if;
}
else {
my_CFRelease(&net_if);
}
return (dict);
}
STATIC Boolean
setInterfaceEAPOLConfiguration(EAPOLClientConfigurationRef cfg,
SCNetworkInterfaceRef net_if,
CFDictionaryRef dict)
{
CFRange r;
Boolean ret;
ret = SCNetworkInterfaceSetExtendedConfiguration(net_if, kEAPOL, dict);
if (ret == FALSE) {
return (ret);
}
if (cfg->sc_changed_if == NULL) {
cfg->sc_changed_if = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
}
r.location = 0;
r.length = CFArrayGetCount(cfg->sc_changed_if);
if (CFArrayContainsValue(cfg->sc_changed_if, r, net_if) == FALSE) {
CFArrayAppendValue(cfg->sc_changed_if, net_if);
}
return (TRUE);
}
STATIC Boolean
saveInterfaceEAPOLConfiguration(EAPOLClientConfigurationRef cfg,
Boolean * changed_p)
{
AuthorizationExternalForm * auth_ext_p;
int count;
int i;
SCPreferencesRef prefs = NULL;
Boolean ret = FALSE;
*changed_p = FALSE;
if (cfg->sc_changed_if == NULL) {
return (TRUE);
}
auth_ext_p = EAPOLClientConfigurationGetAuthorizationExternalForm(cfg);
if (auth_ext_p != NULL) {
AuthorizationRef auth;
OSStatus status;
status = AuthorizationCreateFromExternalForm(auth_ext_p, &auth);
if (status != errAuthorizationSuccess) {
syslog(LOG_ERR,
"EAPOLClientConfiguration: can't allocate Authorization, %d",
(int)status);
goto done;
}
prefs = SCPreferencesCreateWithAuthorization(NULL,
kPrefsName, NULL,
auth);
AuthorizationFree(auth, kAuthorizationFlagDefaults);
}
else {
prefs = SCPreferencesCreate(NULL, kPrefsName, NULL);
}
count = CFArrayGetCount(cfg->sc_changed_if);
for (i = 0; i < count; i++) {
CFDictionaryRef dict;
CFStringRef if_name;
SCNetworkInterfaceRef net_if;
net_if = (SCNetworkInterfaceRef)
CFArrayGetValueAtIndex(cfg->sc_changed_if, i);
if_name = SCNetworkInterfaceGetBSDName(net_if);
if (if_name == NULL) {
syslog(LOG_ERR, "EAPOLClientConfiguration: missing BSD name");
continue;
}
dict = SCNetworkInterfaceGetExtendedConfiguration(net_if, kEAPOL);
if (set_eapol_configuration(prefs, if_name, dict) == FALSE) {
continue;
}
}
ret = SCPreferencesCommitChanges(prefs);
if (ret == FALSE) {
syslog(LOG_NOTICE,
"EAPOLClientConfigurationSave SCPreferencesCommitChanges"
" failed %s", SCErrorString(SCError()));
goto done;
}
SCPreferencesApplyChanges(prefs);
*changed_p = TRUE;
done:
my_CFRelease(&cfg->sc_changed_if);
my_CFRelease(&prefs);
return (ret);
}
STATIC CFStringRef __EAPOLClientConfigurationCopyDebugDesc(CFTypeRef cf);
STATIC void __EAPOLClientConfigurationDeallocate(CFTypeRef cf);
STATIC CFTypeID __kEAPOLClientConfigurationTypeID = _kCFRuntimeNotATypeID;
STATIC const CFRuntimeClass __EAPOLClientConfigurationClass = {
0,
"EAPOLClientConfiguration",
NULL,
NULL,
__EAPOLClientConfigurationDeallocate,
NULL,
NULL,
NULL,
__EAPOLClientConfigurationCopyDebugDesc
};
STATIC CFStringRef
__EAPOLClientConfigurationCopyDebugDesc(CFTypeRef cf)
{
CFAllocatorRef allocator = CFGetAllocator(cf);
EAPOLClientConfigurationRef cfg = (EAPOLClientConfigurationRef)cf;
CFMutableStringRef result;
result = CFStringCreateMutable(allocator, 0);
if (cfg->auth_ext_p == NULL) {
CFStringAppendFormat(result, NULL,
CFSTR("<EAPOLClientConfiguration %p [%p]> {"),
cf, allocator);
}
else {
CFStringAppendFormat(result, NULL,
CFSTR("<EAPOLClientConfiguration %p [%p] auth> {"),
cf, allocator);
}
CFStringAppendFormat(result, NULL, CFSTR("profiles = %@"), cfg->profiles);
CFStringAppendFormat(result, NULL, CFSTR("ssids = %@"), cfg->ssids);
CFStringAppend(result, CFSTR("}"));
return (result);
}
STATIC void
__EAPOLClientConfigurationDeallocate(CFTypeRef cf)
{
EAPOLClientConfigurationRef cfg = (EAPOLClientConfigurationRef)cf;
if (cfg->auth_ext_p != NULL) {
free(cfg->auth_ext_p);
cfg->auth_ext_p = NULL;
}
my_CFRelease(&cfg->eap_prefs);
my_CFRelease(&cfg->sc_prefs);
my_CFRelease(&cfg->profiles);
my_CFRelease(&cfg->ssids);
my_CFRelease(&cfg->def_auth_props);
my_CFRelease(&cfg->sc_changed_if);
return;
}
STATIC void
__EAPOLClientConfigurationInitialize(void)
{
__kEAPOLClientConfigurationTypeID
= _CFRuntimeRegisterClass(&__EAPOLClientConfigurationClass);
return;
}
STATIC void
__EAPOLClientConfigurationRegisterClass(void)
{
STATIC pthread_once_t initialized = PTHREAD_ONCE_INIT;
pthread_once(&initialized, __EAPOLClientConfigurationInitialize);
return;
}
STATIC EAPOLClientConfigurationRef
__EAPOLClientConfigurationAllocate(CFAllocatorRef allocator)
{
EAPOLClientConfigurationRef cfg;
int size;
__EAPOLClientConfigurationRegisterClass();
size = sizeof(*cfg) - sizeof(CFRuntimeBase);
cfg = (EAPOLClientConfigurationRef)
_CFRuntimeCreateInstance(allocator,
__kEAPOLClientConfigurationTypeID, size, NULL);
bzero(((void *)cfg) + sizeof(CFRuntimeBase), size);
return (cfg);
}
CFTypeID
EAPOLClientConfigurationGetTypeID(void)
{
__EAPOLClientConfigurationRegisterClass();
return (__kEAPOLClientConfigurationTypeID);
}
EAPOLClientConfigurationRef
EAPOLClientConfigurationCreateInternal(CFAllocatorRef allocator,
AuthorizationRef auth)
{
EAPOLClientConfigurationRef cfg;
cfg = __EAPOLClientConfigurationAllocate(allocator);
if (cfg == NULL) {
return (NULL);
}
if (auth != NULL) {
cfg->eap_prefs
= SCPreferencesCreateWithAuthorization(allocator,
kPrefsName,
kEAPOLClientConfigurationPrefsID,
auth);
}
else {
cfg->eap_prefs = SCPreferencesCreate(allocator, kPrefsName,
kEAPOLClientConfigurationPrefsID);
}
if (cfg->eap_prefs == NULL) {
goto failed;
}
if (auth != NULL) {
AuthorizationExternalForm * auth_ext_p;
OSStatus status;
auth_ext_p = malloc(sizeof(*auth_ext_p));
status = AuthorizationMakeExternalForm(auth, auth_ext_p);
if (status != errAuthorizationSuccess) {
free(auth_ext_p);
goto failed;
}
cfg->auth_ext_p = auth_ext_p;
}
import_profiles(cfg);
cfg->def_auth_props = copy_def_auth_props(cfg->eap_prefs);
return (cfg);
failed:
my_CFRelease(&cfg);
return (NULL);
}
EAPOLClientConfigurationRef
EAPOLClientConfigurationCreate(CFAllocatorRef allocator)
{
return (EAPOLClientConfigurationCreateInternal(allocator, NULL));
}
EAPOLClientConfigurationRef
EAPOLClientConfigurationCreateWithAuthorization(CFAllocatorRef allocator,
AuthorizationRef auth)
{
if (auth == NULL) {
return (NULL);
}
return (EAPOLClientConfigurationCreateInternal(allocator, auth));
}
Boolean
EAPOLClientConfigurationSave(EAPOLClientConfigurationRef cfg)
{
Boolean changed = FALSE;
CFDictionaryRef existing_prefs_dict;
CFDictionaryRef prefs_dict;
Boolean ret = FALSE;
prefs_dict = export_profiles(cfg);
if (prefs_dict == NULL) {
syslog(LOG_NOTICE,
"EAPOLClientConfigurationSave copy_profiles() failed");
goto done;
}
existing_prefs_dict = SCPreferencesGetValue(cfg->eap_prefs,
kConfigurationKeyProfiles);
if (cfg->def_auth_props_changed == FALSE
&& my_CFEqual(existing_prefs_dict, prefs_dict)) {
}
else {
if (cfg->def_auth_props_changed) {
ret = SCPreferencesSetValue(cfg->eap_prefs,
kConfigurationKeyDefaultAuthenticationProperties,
cfg->def_auth_props);
if (ret == FALSE) {
syslog(LOG_NOTICE,
"EAPOLClientConfigurationSave SCPreferencesSetValue"
" failed %s",
SCErrorString(SCError()));
goto done;
}
}
ret = SCPreferencesSetValue(cfg->eap_prefs, kConfigurationKeyProfiles,
prefs_dict);
if (ret == FALSE) {
syslog(LOG_NOTICE,
"EAPOLClientConfigurationSave SCPreferencesSetValue"
" failed %s",
SCErrorString(SCError()));
goto done;
}
ret = SCPreferencesCommitChanges(cfg->eap_prefs);
if (ret == FALSE) {
syslog(LOG_NOTICE,
"EAPOLClientConfigurationSave SCPreferencesCommitChanges"
" failed %s", SCErrorString(SCError()));
return (FALSE);
}
cfg->def_auth_props_changed = FALSE;
SCPreferencesApplyChanges(cfg->eap_prefs);
changed = TRUE;
}
{
Boolean this_changed = FALSE;
ret = saveInterfaceEAPOLConfiguration(cfg, &this_changed);
if (ret == FALSE) {
goto done;
}
if (this_changed) {
changed = TRUE;
}
}
my_CFRelease(&cfg->sc_prefs);
done:
my_CFRelease(&prefs_dict);
if (changed) {
notify_post(kEAPOLClientConfigurationChangedNotifyKey);
}
return (ret);
}
CFArrayRef
EAPOLClientConfigurationCopyProfiles(EAPOLClientConfigurationRef cfg)
{
CFAllocatorRef allocator = CFGetAllocator(cfg);
int count;
CFArrayRef profiles;
const void * * values;
count = CFDictionaryGetCount(cfg->profiles);
if (count == 0) {
return (NULL);
}
values = (const void * *)malloc(sizeof(*values) * count);
CFDictionaryGetKeysAndValues(cfg->profiles, NULL, values);
profiles = CFArrayCreate(allocator, values, count, &kCFTypeArrayCallBacks);
free(values);
return (profiles);
}
EAPOLClientProfileRef
EAPOLClientConfigurationGetProfileWithID(EAPOLClientConfigurationRef cfg,
CFStringRef profileID)
{
return ((EAPOLClientProfileRef)
CFDictionaryGetValue(cfg->profiles, profileID));
}
EAPOLClientProfileRef
EAPOLClientConfigurationGetProfileWithWLANSSID(EAPOLClientConfigurationRef cfg,
CFDataRef ssid)
{
CFStringRef profileID;
profileID = CFDictionaryGetValue(cfg->ssids, ssid);
if (profileID == NULL) {
return (NULL);
}
return ((EAPOLClientProfileRef)
CFDictionaryGetValue(cfg->profiles, profileID));
}
Boolean
EAPOLClientConfigurationRemoveProfile(EAPOLClientConfigurationRef cfg,
EAPOLClientProfileRef profile)
{
CFStringRef profileID = EAPOLClientProfileGetID(profile);
CFDataRef ssid;
if (EAPOLClientConfigurationGetProfileWithID(cfg, profileID) != profile) {
return (FALSE);
}
ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(profile, NULL);
if (ssid != NULL) {
CFDictionaryRemoveValue(cfg->ssids, ssid);
}
CFDictionaryRemoveValue(cfg->profiles, profileID);
return (TRUE);
}
Boolean
EAPOLClientConfigurationAddProfile(EAPOLClientConfigurationRef cfg,
EAPOLClientProfileRef profile)
{
CFStringRef profileID = EAPOLClientProfileGetID(profile);
CFDataRef ssid;
if (profile->cfg != NULL) {
return (FALSE);
}
if (EAPOLClientConfigurationGetProfileWithID(cfg, profileID) != NULL) {
return (FALSE);
}
ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(profile, NULL);
if (ssid != NULL
&& EAPOLClientConfigurationGetProfileWithWLANSSID(cfg, ssid) != NULL) {
return (FALSE);
}
CFDictionarySetValue(cfg->profiles, profileID, profile);
if (ssid != NULL) {
CFDictionarySetValue(cfg->ssids, ssid, profileID);
}
EAPOLClientProfileSetConfiguration(profile, cfg);
return (TRUE);
}
CFArrayRef
EAPOLClientConfigurationCopyMatchingProfiles(EAPOLClientConfigurationRef cfg,
EAPOLClientProfileRef profile)
{
int count;
EAPOLClientProfileRef existing_profile;
CFStringRef profileID = EAPOLClientProfileGetID(profile);
CFDataRef ssid;
const void * values[2] = { NULL, NULL };
count = 0;
existing_profile = EAPOLClientConfigurationGetProfileWithID(cfg, profileID);
if (existing_profile != NULL) {
values[count] = existing_profile;
count++;
}
ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(profile, NULL);
if (ssid != NULL) {
existing_profile
= EAPOLClientConfigurationGetProfileWithWLANSSID(cfg,
ssid);
if (existing_profile != NULL && values[0] != existing_profile) {
values[count] = existing_profile;
count++;
}
}
if (count == 0) {
return (NULL);
}
return (CFArrayCreate(CFGetAllocator(cfg), values, count,
&kCFTypeArrayCallBacks));
}
CFArrayRef
EAPOLClientConfigurationCopyLoginWindowProfiles(EAPOLClientConfigurationRef cfg,
CFStringRef if_name)
{
int count;
int i;
CFDictionaryRef dict;
CFArrayRef profile_ids;
CFMutableArrayRef ret_profiles = NULL;
dict = get_eapol_configuration(get_sc_prefs(cfg), if_name, NULL);
if (dict == NULL) {
goto done;
}
profile_ids = CFDictionaryGetValue(dict, kLoginWindowProfileIDs);
if (isA_CFArray(profile_ids) == NULL) {
goto done;
}
count = CFArrayGetCount(profile_ids);
if (count == 0) {
goto done;
}
ret_profiles = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
for (i = 0; i < count; i++) {
CFStringRef profileID;
EAPOLClientProfileRef profile;
profileID = (CFStringRef)CFArrayGetValueAtIndex(profile_ids, i);
if (isA_CFString(profileID) == NULL) {
continue;
}
profile = EAPOLClientConfigurationGetProfileWithID(cfg, profileID);
if (profile != NULL) {
CFArrayAppendValue(ret_profiles, profile);
}
}
if (CFArrayGetCount(ret_profiles) == 0) {
my_CFRelease(&ret_profiles);
}
done:
return (ret_profiles);
}
Boolean
EAPOLClientConfigurationSetLoginWindowProfiles(EAPOLClientConfigurationRef cfg,
CFStringRef if_name,
CFArrayRef profiles)
{
CFDictionaryRef dict;
CFArrayRef existing_profile_ids = NULL;
SCNetworkInterfaceRef net_if = NULL;
CFMutableDictionaryRef new_dict = NULL;
CFMutableArrayRef profile_ids = NULL;
Boolean ret = FALSE;
dict = get_eapol_configuration(get_sc_prefs(cfg), if_name, &net_if);
if (net_if == NULL) {
goto done;
}
if (dict != NULL) {
existing_profile_ids
= CFDictionaryGetValue(dict, kLoginWindowProfileIDs);
existing_profile_ids = isA_CFArray(existing_profile_ids);
}
if (profiles == NULL || CFArrayGetCount(profiles) == 0) {
profile_ids = NULL;
}
else {
int count;
int i;
CFRange r = { 0, 0 };
count = CFArrayGetCount(profiles);
profile_ids = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
for (i = 0; i < count; i++) {
EAPOLClientProfileRef profile;
CFStringRef profileID;
profile = (EAPOLClientProfileRef)
CFArrayGetValueAtIndex(profiles, i);
profileID = EAPOLClientProfileGetID(profile);
if (CFArrayContainsValue(profile_ids, r, profileID) == FALSE) {
CFArrayAppendValue(profile_ids, profileID);
r.length++;
}
}
}
if (my_CFEqual(existing_profile_ids, profile_ids)) {
ret = TRUE;
goto done;
}
if (dict != NULL) {
new_dict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
CFDictionaryRemoveValue(new_dict, kEAPClientPropAcceptEAPTypes);
CFDictionaryRemoveValue(new_dict, kSCResvInactive);
}
else {
new_dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if (profile_ids == NULL) {
CFDictionaryRemoveValue(new_dict, kLoginWindowProfileIDs);
if (CFDictionaryGetCount(new_dict) == 0) {
my_CFRelease(&new_dict);
}
}
else {
CFDictionarySetValue(new_dict, kLoginWindowProfileIDs, profile_ids);
}
if (setInterfaceEAPOLConfiguration(cfg, net_if, new_dict)
== FALSE) {
goto done;
}
ret = TRUE;
done:
my_CFRelease(&new_dict);
my_CFRelease(&profile_ids);
my_CFRelease(&net_if);
return (ret);
}
EAPOLClientProfileRef
EAPOLClientConfigurationGetSystemProfile(EAPOLClientConfigurationRef cfg,
CFStringRef if_name)
{
CFDictionaryRef dict;
SCNetworkInterfaceRef net_if = NULL;
EAPOLClientProfileRef profile = NULL;
CFStringRef profileID;
dict = get_eapol_configuration(get_sc_prefs(cfg), if_name, &net_if);
if (dict != NULL
&& !CFEqual(SCNetworkInterfaceGetInterfaceType(net_if),
kSCNetworkInterfaceTypeIEEE80211)) {
profileID = CFDictionaryGetValue(dict, kSystemProfileID);
if (isA_CFString(profileID) != NULL) {
profile = EAPOLClientConfigurationGetProfileWithID(cfg, profileID);
}
}
my_CFRelease(&net_if);
return (profile);
}
Boolean
EAPOLClientConfigurationSetSystemProfile(EAPOLClientConfigurationRef cfg,
CFStringRef if_name,
EAPOLClientProfileRef profile)
{
CFDictionaryRef dict;
CFStringRef existing_profileID = NULL;
CFMutableDictionaryRef new_dict = NULL;
SCNetworkInterfaceRef net_if = NULL;
CFStringRef profileID = NULL;
Boolean ret = FALSE;
if (profile != NULL) {
profileID = EAPOLClientProfileGetID(profile);
}
dict = get_eapol_configuration(get_sc_prefs(cfg), if_name, &net_if);
if (net_if == NULL) {
goto done;
}
if (CFEqual(SCNetworkInterfaceGetInterfaceType(net_if),
kSCNetworkInterfaceTypeIEEE80211)) {
goto done;
}
if (dict != NULL) {
existing_profileID
= CFDictionaryGetValue(dict, kSystemProfileID);
}
if (my_CFEqual(existing_profileID, profileID)) {
ret = TRUE;
goto done;
}
if (dict != NULL) {
new_dict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
CFDictionaryRemoveValue(new_dict, kEAPClientPropAcceptEAPTypes);
CFDictionaryRemoveValue(new_dict, kSCResvInactive);
}
else {
new_dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if (profileID == NULL) {
CFDictionaryRemoveValue(new_dict, kSystemProfileID);
if (CFDictionaryGetCount(new_dict) == 0) {
my_CFRelease(&new_dict);
}
}
else {
CFDictionarySetValue(new_dict, kSystemProfileID, profileID);
}
if (setInterfaceEAPOLConfiguration(cfg, net_if, new_dict)
== FALSE) {
goto done;
}
ret = TRUE;
done:
my_CFRelease(&new_dict);
my_CFRelease(&net_if);
return (ret);
}
CFDictionaryRef
EAPOLClientConfigurationCopyAllSystemProfiles(EAPOLClientConfigurationRef cfg)
{
return (copy_profiles_for_mode(cfg, kEAPOLControlModeSystem));
}
CFDictionaryRef
EAPOLClientConfigurationCopyAllLoginWindowProfiles(EAPOLClientConfigurationRef cfg)
{
return (copy_profiles_for_mode(cfg, kEAPOLControlModeLoginWindow));
}
CFDictionaryRef
EAPOLClientConfigurationGetDefaultAuthenticationProperties(EAPOLClientConfigurationRef cfg)
{
return (cfg->def_auth_props);
}
Boolean
EAPOLClientConfigurationSetDefaultAuthenticationProperties(EAPOLClientConfigurationRef cfg,
CFDictionaryRef auth_props)
{
CFArrayRef accept_types;
my_CFRelease(&cfg->def_auth_props);
if (auth_props == NULL) {
cfg->def_auth_props = copy_def_auth_props(cfg->eap_prefs);
cfg->def_auth_props_changed = TRUE;
return (TRUE);
}
accept_types = CFDictionaryGetValue(auth_props,
kEAPClientPropAcceptEAPTypes);
if (accept_types_valid(accept_types) == FALSE) {
return (FALSE);
}
cfg->def_auth_props = CFRetain(auth_props);
cfg->def_auth_props_changed = TRUE;
return (TRUE);
}
PRIVATE_EXTERN void
EAPOLClientConfigurationSetProfileForSSID(EAPOLClientConfigurationRef cfg,
CFDataRef ssid,
EAPOLClientProfileRef profile)
{
if (profile == NULL) {
CFDictionaryRemoveValue(cfg->ssids, ssid);
}
else {
CFDictionarySetValue(cfg->ssids, ssid,
EAPOLClientProfileGetID(profile));
}
return;
}
PRIVATE_EXTERN AuthorizationExternalForm *
EAPOLClientConfigurationGetAuthorizationExternalForm(EAPOLClientConfigurationRef cfg)
{
return (cfg->auth_ext_p);
}