EAPOLClientProfile.c [plain text]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <TargetConditionals.h>
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
#include <pthread.h>
#include "EAPClientProperties.h"
#include "EAPOLClientConfigurationInternal.h"
#include "symbol_scope.h"
#include "myCFUtil.h"
#define kProfileKeyProfileID CFSTR("ProfileID")
#define kProfileKeyUserDefinedName CFSTR("UserDefinedName")
#define kProfileKeyAuthenticationProperties CFSTR("AuthenticationProperties")
#define kProfileKeyInformation CFSTR("Information")
#define kProfileKeyWLAN CFSTR("WLAN")
#define kProfileKeySSID CFSTR("SSID")
#define kProfileKeySecurityType CFSTR("SecurityType")
PRIVATE_EXTERN Boolean
accept_types_valid(CFArrayRef accept)
{
int count;
int i;
if (isA_CFArray(accept) == NULL) {
return (FALSE);
}
count = CFArrayGetCount(accept);
if (count == 0) {
return (FALSE);
}
for (i = 0; i < count; i++) {
CFNumberRef type = CFArrayGetValueAtIndex(accept, i);
if (isA_CFNumber(type) == NULL) {
return (FALSE);
}
}
return (TRUE);
}
STATIC Boolean
applicationID_is_valid(CFStringRef applicationID)
{
CFRange r;
if (CFStringGetLength(applicationID) < 3) {
return (FALSE);
}
r = CFStringFind(applicationID, CFSTR("."), 0);
if (r.location == kCFNotFound) {
return (FALSE);
}
return (TRUE);
}
STATIC CFStringRef __EAPOLClientProfileCopyDebugDesc(CFTypeRef cf);
STATIC void __EAPOLClientProfileDeallocate(CFTypeRef cf);
STATIC Boolean __EAPOLClientProfileEqual(CFTypeRef cf1, CFTypeRef cf2);
STATIC CFHashCode __EAPOLClientProfileHash(CFTypeRef cf);
STATIC CFTypeID __kEAPOLClientProfileTypeID = _kCFRuntimeNotATypeID;
STATIC const CFRuntimeClass __EAPOLClientProfileClass = {
0,
"EAPOLClientProfile",
NULL,
NULL,
__EAPOLClientProfileDeallocate,
__EAPOLClientProfileEqual,
__EAPOLClientProfileHash,
NULL,
__EAPOLClientProfileCopyDebugDesc
};
STATIC CFStringRef
__EAPOLClientProfileCopyDebugDesc(CFTypeRef cf)
{
CFAllocatorRef allocator = CFGetAllocator(cf);
EAPOLClientProfileRef profile = (EAPOLClientProfileRef)cf;
CFMutableStringRef result;
result = CFStringCreateMutable(allocator, 0);
CFStringAppendFormat(result, NULL,
CFSTR("<EAPOLClientProfile %p [%p]> {"),
cf, allocator);
CFStringAppendFormat(result, NULL,
CFSTR("ProfileID = %@"),
profile->uuid);
if (profile->user_defined_name != NULL) {
CFStringAppendFormat(result, NULL,
CFSTR(" Name = '%@'"),
profile->user_defined_name);
}
if (profile->WLAN.ssid != NULL) {
CFStringRef ssid_str = my_CFStringCreateWithData(profile->WLAN.ssid);
CFStringAppendFormat(result, NULL,
CFSTR(", WLAN SSID %@ [%@]"),
ssid_str, profile->WLAN.security_type);
CFRelease(ssid_str);
}
if (profile->auth_props != NULL) {
CFStringAppendFormat(result, NULL,
CFSTR(", auth_props = %@"),
profile->auth_props);
}
if (profile->information != NULL
&& CFDictionaryGetCount(profile->information) != 0) {
CFStringAppendFormat(result, NULL,
CFSTR(", info = %@"),
profile->information);
}
CFStringAppendFormat(result, NULL, CFSTR("}"));
return result;
}
STATIC void
__EAPOLClientProfileDeallocate(CFTypeRef cf)
{
EAPOLClientProfileRef profile = (EAPOLClientProfileRef)cf;
my_CFRelease(&profile->uuid);
my_CFRelease(&profile->auth_props);
my_CFRelease(&profile->user_defined_name);
my_CFRelease(&profile->WLAN.ssid);
my_CFRelease(&profile->WLAN.security_type);
my_CFRelease(&profile->information);
return;
}
STATIC Boolean
__EAPOLClientProfileEqual(CFTypeRef cf1, CFTypeRef cf2)
{
EAPOLClientProfileRef prof1 = (EAPOLClientProfileRef)cf1;
EAPOLClientProfileRef prof2 = (EAPOLClientProfileRef)cf2;
if (CFEqual(prof1->uuid, prof2->uuid) == FALSE) {
return (FALSE);
}
if (my_CFEqual(prof1->auth_props, prof2->auth_props) == FALSE) {
return (FALSE);
}
if (my_CFEqual(prof1->user_defined_name,
prof2->user_defined_name) == FALSE) {
return (FALSE);
}
if (my_CFEqual(prof1->WLAN.ssid, prof2->WLAN.ssid) == FALSE) {
return (FALSE);
}
if (my_CFEqual(prof1->WLAN.security_type, prof2->WLAN.security_type)
== FALSE) {
return (FALSE);
}
if (my_CFEqual(prof1->information, prof2->information) == FALSE) {
return (FALSE);
}
return (TRUE);
}
STATIC CFHashCode
__EAPOLClientProfileHash(CFTypeRef cf)
{
EAPOLClientProfileRef profile = (EAPOLClientProfileRef)cf;
return (CFHash(profile->uuid));
}
STATIC void
__EAPOLClientProfileInitialize(void)
{
__kEAPOLClientProfileTypeID
= _CFRuntimeRegisterClass(&__EAPOLClientProfileClass);
return;
}
STATIC void
__EAPOLClientProfileRegisterClass(void)
{
STATIC pthread_once_t initialized = PTHREAD_ONCE_INIT;
pthread_once(&initialized, __EAPOLClientProfileInitialize);
return;
}
STATIC EAPOLClientProfileRef
__EAPOLClientProfileAllocate(CFAllocatorRef allocator)
{
EAPOLClientProfileRef profile;
int size;
__EAPOLClientProfileRegisterClass();
size = sizeof(*profile) - sizeof(CFRuntimeBase);
profile = (EAPOLClientProfileRef)
_CFRuntimeCreateInstance(allocator,
__kEAPOLClientProfileTypeID, size, NULL);
bzero(((void *)profile) + sizeof(CFRuntimeBase), size);
return (profile);
}
CFTypeID
EAPOLClientProfileGetTypeID(void)
{
__EAPOLClientProfileRegisterClass();
return (__kEAPOLClientProfileTypeID);
}
EAPOLClientProfileRef
EAPOLClientProfileCreate(EAPOLClientConfigurationRef cfg)
{
CFAllocatorRef alloc = CFGetAllocator(cfg);
EAPOLClientProfileRef profile;
profile = __EAPOLClientProfileAllocate(alloc);
if (profile == NULL) {
return (NULL);
}
profile->uuid = my_CFUUIDStringCreate(alloc);
if (EAPOLClientConfigurationAddProfile(cfg, profile) == FALSE) {
my_CFRelease(&profile);
}
return (profile);
}
CFStringRef
EAPOLClientProfileGetUserDefinedName(EAPOLClientProfileRef profile)
{
return (profile->user_defined_name);
}
void
EAPOLClientProfileSetUserDefinedName(EAPOLClientProfileRef profile,
CFStringRef user_defined_name)
{
if (user_defined_name != NULL) {
CFRetain(user_defined_name);
}
if (profile->user_defined_name != NULL) {
CFRelease(profile->user_defined_name);
}
profile->user_defined_name = user_defined_name;
return;
}
CFStringRef
EAPOLClientProfileGetID(EAPOLClientProfileRef profile)
{
return (profile->uuid);
}
CFDictionaryRef
EAPOLClientProfileGetAuthenticationProperties(EAPOLClientProfileRef profile)
{
return (profile->auth_props);
}
void
EAPOLClientProfileSetAuthenticationProperties(EAPOLClientProfileRef profile,
CFDictionaryRef auth_props)
{
if (auth_props != NULL) {
CFRetain(auth_props);
}
if (profile->auth_props != NULL) {
CFRelease(profile->auth_props);
}
profile->auth_props = auth_props;
return;
}
CFDataRef
EAPOLClientProfileGetWLANSSIDAndSecurityType(EAPOLClientProfileRef profile,
CFStringRef * ret_security_type)
{
if (profile->WLAN.ssid != NULL) {
if (ret_security_type != NULL) {
*ret_security_type = profile->WLAN.security_type;
}
return (profile->WLAN.ssid);
}
if (ret_security_type != NULL) {
*ret_security_type = NULL;
}
return (NULL);
}
Boolean
EAPOLClientProfileSetWLANSSIDAndSecurityType(EAPOLClientProfileRef profile,
CFDataRef ssid,
CFStringRef security_type)
{
EAPOLClientProfileRef existing_profile;
if (ssid != NULL) {
if (security_type == NULL) {
return (FALSE);
}
if (profile->cfg != NULL) {
existing_profile
= EAPOLClientConfigurationGetProfileWithWLANSSID(profile->cfg,
ssid);
if (existing_profile != NULL && existing_profile != profile) {
return (FALSE);
}
}
}
else if (security_type != NULL) {
return (FALSE);
}
if (profile->WLAN.ssid != NULL && profile->cfg != NULL) {
EAPOLClientConfigurationSetProfileForSSID(profile->cfg,
profile->WLAN.ssid,
NULL);
}
if (ssid != NULL) {
CFRetain(ssid);
if (profile->cfg != NULL) {
EAPOLClientConfigurationSetProfileForSSID(profile->cfg,
ssid,
profile);
}
}
if (security_type != NULL) {
CFRetain(security_type);
}
if (profile->WLAN.ssid != NULL) {
CFRelease(profile->WLAN.ssid);
}
if (profile->WLAN.security_type != NULL) {
CFRelease(profile->WLAN.security_type);
}
profile->WLAN.ssid = ssid;
profile->WLAN.security_type = security_type;
return (TRUE);
}
Boolean
EAPOLClientProfileSetInformation(EAPOLClientProfileRef profile,
CFStringRef applicationID,
CFDictionaryRef information)
{
if (applicationID_is_valid(applicationID) == FALSE) {
return (FALSE);
}
if (information == NULL) {
if (profile->information != NULL) {
CFDictionaryRemoveValue(profile->information, applicationID);
}
}
else {
if (isA_CFDictionary(information) == NULL) {
return (FALSE);
}
if (profile->information == NULL) {
profile->information
= CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
CFDictionarySetValue(profile->information, applicationID, information);
}
return (TRUE);
}
CFDictionaryRef
EAPOLClientProfileGetInformation(EAPOLClientProfileRef profile,
CFStringRef applicationID)
{
CFDictionaryRef dict;
if (profile->information == NULL) {
return (NULL);
}
if (applicationID_is_valid(applicationID) == FALSE) {
return (NULL);
}
dict = CFDictionaryGetValue(profile->information, applicationID);
return (isA_CFDictionary(dict));
}
CFPropertyListRef
EAPOLClientProfileCreatePropertyList(EAPOLClientProfileRef profile)
{
CFMutableDictionaryRef dict;
CFStringRef profileID;
dict = EAPOLClientProfileCreateDictAndProfileID(profile, &profileID);
if (dict == NULL) {
return (NULL);
}
CFDictionarySetValue(dict, kProfileKeyProfileID, profileID);
return ((CFPropertyListRef)dict);
}
EAPOLClientProfileRef
EAPOLClientProfileCreateWithPropertyList(CFPropertyListRef external_format)
{
CFDictionaryRef dict = (CFDictionaryRef)external_format;
CFStringRef profileID;
if (isA_CFDictionary(dict) == NULL) {
return (NULL);
}
profileID = CFDictionaryGetValue(dict, kProfileKeyProfileID);
if (isA_CFString(profileID) == NULL) {
return (NULL);
}
return (EAPOLClientProfileCreateWithDictAndProfileID(dict, profileID));
}
PRIVATE_EXTERN CFMutableDictionaryRef
EAPOLClientProfileCreateDictAndProfileID(EAPOLClientProfileRef profile,
CFStringRef * ret_profileID)
{
CFArrayRef accept_types = NULL;
CFMutableDictionaryRef dict;
if (profile->auth_props != NULL) {
accept_types = CFDictionaryGetValue(profile->auth_props,
kEAPClientPropAcceptEAPTypes);
}
if (accept_types_valid(accept_types) == FALSE) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" missing/invalid AuthenticationProperties"),
EAPOLClientProfileGetID(profile));
return (NULL);
}
dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (ret_profileID != NULL) {
*ret_profileID = CFRetain(profile->uuid);
}
CFDictionarySetValue(dict,
kProfileKeyAuthenticationProperties,
profile->auth_props);
if (profile->user_defined_name != NULL) {
CFDictionarySetValue(dict,
kProfileKeyUserDefinedName,
profile->user_defined_name);
}
if (profile->information != NULL
&& CFDictionaryGetCount(profile->information) != 0) {
CFDictionarySetValue(dict,
kProfileKeyInformation,
profile->information);
}
if (profile->WLAN.ssid != NULL) {
const void * keys[2];
CFDictionaryRef WLAN;
const void * values[2];
keys[0] = kProfileKeySSID;
values[0] = profile->WLAN.ssid;
keys[1] = kProfileKeySecurityType;
values[1] = profile->WLAN.security_type;
WLAN = CFDictionaryCreate(NULL, keys, values, 2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(dict, kProfileKeyWLAN, WLAN);
CFRelease(WLAN);
}
return (dict);
}
PRIVATE_EXTERN EAPOLClientProfileRef
EAPOLClientProfileCreateWithDictAndProfileID(CFDictionaryRef dict,
CFStringRef profileID)
{
CFAllocatorRef alloc = CFGetAllocator(dict);
CFArrayRef accept_types;
CFDictionaryRef information;
CFDictionaryRef eap_config;
EAPOLClientProfileRef profile;
CFStringRef security_type = NULL;
CFStringRef user_defined_name;
CFDataRef ssid = NULL;
CFDictionaryRef wlan;
eap_config = CFDictionaryGetValue(dict,
kProfileKeyAuthenticationProperties);
if (isA_CFDictionary(eap_config) == NULL
|| CFDictionaryGetCount(eap_config) == 0) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" missing/invalid %@ property"),
profileID, kProfileKeyAuthenticationProperties);
return (NULL);
}
accept_types = CFDictionaryGetValue(eap_config,
kEAPClientPropAcceptEAPTypes);
if (accept_types_valid(accept_types) == FALSE) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" missing/invalid %@ property in %@"),
profileID, kEAPClientPropAcceptEAPTypes,
kProfileKeyAuthenticationProperties);
return (NULL);
}
wlan = CFDictionaryGetValue(dict, kProfileKeyWLAN);
if (wlan != NULL) {
if (isA_CFDictionary(wlan) == NULL) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" invalid %@ property"),
profileID, kProfileKeyWLAN);
return (NULL);
}
ssid = CFDictionaryGetValue(wlan, kProfileKeySSID);
if (isA_CFData(ssid) == NULL) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" invalid/missing %@ property in %@"),
profileID, kProfileKeySSID, kProfileKeyWLAN);
return (NULL);
}
security_type = CFDictionaryGetValue(wlan, kProfileKeySecurityType);
if (isA_CFString(security_type) == NULL) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" invalid/missing %@ property in %@"),
profileID, kProfileKeySecurityType, kProfileKeyWLAN);
return (NULL);
}
}
user_defined_name = CFDictionaryGetValue(dict, kProfileKeyUserDefinedName);
if (user_defined_name != NULL && isA_CFString(user_defined_name) == NULL) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" invalid %@ property"),
profileID, kProfileKeyUserDefinedName);
return (NULL);
}
information = CFDictionaryGetValue(dict, kProfileKeyInformation);
if (information != NULL && isA_CFDictionary(information) == NULL) {
SCLog(TRUE, LOG_NOTICE,
CFSTR("EAPOLClientConfiguration: profile %@"
" invalid %@ property"),
profileID, kProfileKeyInformation);
return (NULL);
}
profile = __EAPOLClientProfileAllocate(alloc);
if (profile == NULL) {
return (NULL);
}
profile->uuid = CFRetain(profileID);
EAPOLClientProfileSetUserDefinedName(profile, user_defined_name);
EAPOLClientProfileSetAuthenticationProperties(profile, eap_config);
if (ssid != NULL) {
EAPOLClientProfileSetWLANSSIDAndSecurityType(profile, ssid,
security_type);
}
if (information != NULL) {
profile->information
= CFDictionaryCreateMutableCopy(NULL, 0, information);
}
return (profile);
}
PRIVATE_EXTERN void
EAPOLClientProfileSetConfiguration(EAPOLClientProfileRef profile,
EAPOLClientConfigurationRef cfg)
{
profile->cfg = cfg;
return;
}
PRIVATE_EXTERN EAPOLClientConfigurationRef
EAPOLClientProfileGetConfiguration(EAPOLClientProfileRef profile)
{
return (profile->cfg);
}