Пример #1
0
CFStringRef
EAPOLClientItemIDGetWLANDomain(EAPOLClientItemIDRef itemID)
{
    switch (itemID->type) {
    case kEAPOLClientItemIDTypeWLANDomain:
	return (itemID->u.domain);
    case kEAPOLClientItemIDTypeProfile:
	return (EAPOLClientProfileGetWLANDomain(itemID->u.profile));
    default:
	break;
    }
    return (NULL);
}
Пример #2
0
/*
 * Function: EAPOLClientConfigurationAddProfile
 *
 * Purpose:
 *   Add the specified profile to the configuration.
 *
 * Returns:
 *   FALSE if the profile could not be added, either because:
 *   - the profile is already in the configuration, or
 *   - the profile conflicts with an existing profile (profileID or WLAN SSID)
 *   TRUE if the profile was added successfully.
 */
Boolean
EAPOLClientConfigurationAddProfile(EAPOLClientConfigurationRef cfg,
				   EAPOLClientProfileRef profile)
{
    CFStringRef		domain = NULL;
    CFStringRef		profileID = EAPOLClientProfileGetID(profile);
    CFDataRef		ssid;

    if (profile->cfg != NULL) {
	/* profile is already part of the configuration */
	return (FALSE);
    }
    if (EAPOLClientConfigurationGetProfileWithID(cfg, profileID) != NULL) {
	/* profile already present with that profileID */
	return (FALSE);
    }
    ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(profile, NULL);
    if (ssid != NULL) {
	if (EAPOLClientConfigurationGetProfileWithWLANSSID(cfg, ssid) != NULL) {
	    /* profile already present with that SSID */
	    return (FALSE);
	}
    }
    else {
	domain = EAPOLClientProfileGetWLANDomain(profile);
	if (domain != NULL) {
	    if (EAPOLClientConfigurationGetProfileWithWLANDomain(cfg, domain)
		!= NULL) {
		/* profile already exists with that domain */
		return (FALSE);
	    }
	}
    }
    CFDictionarySetValue(cfg->profiles, profileID, profile);
    if (ssid != NULL) {
	CFDictionarySetValue(cfg->ssids, ssid, profileID);
    }
    else if (domain != NULL) {
	CFDictionarySetValue(cfg->domains, domain, profileID);
    }
    EAPOLClientProfileSetConfiguration(profile, cfg);
    return (TRUE);
}
Пример #3
0
/*
 * Function: EAPOLClientConfigurationCopyMatchingProfiles
 *
 * Purpose:
 *   Find the profile(s) matching the specified profile.
 *   A profile is matched based on the profileID, the WLAN SSID, and
 *   the WLAN domain, all of which must be unique in the configuration.
 *
 *   Usually invoked after calling 
 *   EAPOLClientProfileCreateWithPropertyList() to instantiate a profile
 *   from an external format.
 *
 * Returns:
 *   NULL if no matching profile is part of the configuration,
 *   non-NULL CFArrayRef of EAPOLClientProfileRef if found.
 */
CFArrayRef /* of EAPOLClientProfileRef */
EAPOLClientConfigurationCopyMatchingProfiles(EAPOLClientConfigurationRef cfg,
					     EAPOLClientProfileRef profile)
{
    int				count;
    EAPOLClientProfileRef	matching_profile;
    CFStringRef			profileID = EAPOLClientProfileGetID(profile);
    CFDataRef			ssid;
    const void *		values[2] = { NULL, NULL };
    
    count = 0;
    matching_profile = EAPOLClientConfigurationGetProfileWithID(cfg, profileID);
    if (matching_profile != NULL) {
	values[count] = matching_profile;
	count++;
    }
    matching_profile = NULL;
    ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(profile, NULL);
    if (ssid != NULL) {
	matching_profile 
	    = EAPOLClientConfigurationGetProfileWithWLANSSID(cfg, ssid);
    }
    else {
	CFStringRef		domain;
	
	domain = EAPOLClientProfileGetWLANDomain(profile);
	if (domain != NULL) {
	    matching_profile 
		= EAPOLClientConfigurationGetProfileWithWLANDomain(cfg, domain);
	}
    }
    if (matching_profile != NULL && values[0] != matching_profile) {
	values[count] = matching_profile;
	count++;
    }
    if (count == 0) {
	return (NULL);
    }
    return (CFArrayCreate(CFGetAllocator(cfg), values, count,
			  &kCFTypeArrayCallBacks));
}
Пример #4
0
/*
 * Function: EAPOLClientItemIDSetPasswordItem
 *
 * Purpose:
 *   Set the password item in secure storage for the specified itemID
 *   in the specified domain.
 *
 *   Passing an empty 'username' or 'password' removes the corresponding
 *   attribute.   If both 'username' and 'password' are empty, the item is
 *   also removed.  An empty value is a non-NULL CFDataRef of length 0.
 *
 *   Passing NULL for 'username' or 'password' means that the corresponding
 *   item attribute is left alone.  If both 'username" and 'password' are
 *   NULL, the call has no effect, but TRUE is still returned.
 *
 *   Passing non-NULL, non-empty 'username' or 'password' sets the
 *   corresponding item attribute to the specified value.   If the item
 *   does not exist, it will be created.
 *
 * Returns:
 *   FALSE if the operation did not succeed, TRUE otherwise.
 */
Boolean
EAPOLClientItemIDSetPasswordItem(EAPOLClientItemIDRef itemID,
				 EAPOLClientDomain domain,
				 CFDataRef name, CFDataRef password)
{
    CFMutableDictionaryRef	attrs = NULL;
    CFDataRef			data;
    SecKeychainRef		keychain = NULL;
    CFDataRef			ssid;
    OSStatus			status = errSecParam;
    CFStringRef			unique_string;

    if (name == NULL && password == NULL) {
	return (TRUE);
    }
    switch (domain) {
    case kEAPOLClientDomainUser:
	status = SecKeychainCopyDomainDefault(kSecPreferencesDomainUser,
					      &keychain);
	if (status != noErr) {
	    fprintf(stderr, "EAPOLClientItemIDSetPasswordItem can't get"
		    " User keychain,  %s (%d)\n",
		    EAPSecurityErrorString(status), (int)status);
	    return (FALSE);
	}
	break;
    case kEAPOLClientDomainSystem:
	if (EAPOLClientItemIDGetAuthorizationExternalForm(itemID) != NULL) {
	    return (authEAPOLClientItemIDSetPasswordItem(itemID, name,
							 password));
	}
	status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem,
					      &keychain);
	if (status != noErr) {
	    fprintf(stderr, "EAPOLClientItemIDSetPasswordItem can't get"
		    " System keychain,  %s (%d)\n",
		    EAPSecurityErrorString(status), (int)status);
	    return (FALSE);
	}
	break;
    default:
	return (FALSE);
    }

    /* populate an attributes dictionary */
    attrs = CFDictionaryCreateMutable(NULL, 0,
				      &kCFTypeDictionaryKeyCallBacks,
				      &kCFTypeDictionaryValueCallBacks);

    /* Description */
    data = CFDataCreate(NULL, (UInt8 *)kItemDescription,
			kItemDescriptionLength);
    CFDictionarySetValue(attrs, kEAPSecKeychainPropDescription, data);
    CFRelease(data);

    /* Label */
    switch (itemID->type) {
    case kEAPOLClientItemIDTypeWLANSSID:
	CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel,
			     itemID->u.ssid);
	break;
    case kEAPOLClientItemIDTypeWLANDomain: {
	CFDataRef		label_data;

	label_data = my_CFDataCreateWithString(itemID->u.domain);
	CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel,
			     label_data);
	CFRelease(label_data);
	break;
    }
    case kEAPOLClientItemIDTypeProfileID: {
	CFDataRef		label_data;

	label_data = my_CFDataCreateWithString(itemID->u.profileID);
	CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, label_data);
	CFRelease(label_data);
	break;
    }
    case kEAPOLClientItemIDTypeProfile:
	ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(itemID->u.profile,
							    NULL);
	if (ssid != NULL) {
	    CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel,
				 ssid);
	}
	else {
	    CFStringRef		label;
	    CFDataRef		label_data;
    
	    label = EAPOLClientProfileGetUserDefinedName(itemID->u.profile);
	    if (label == NULL) {
		label = EAPOLClientProfileGetWLANDomain(itemID->u.profile);
		if (label == NULL) {
		    label = EAPOLClientProfileGetID(itemID->u.profile);
		}
	    }
	    label_data = my_CFDataCreateWithString(label);
	    CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, label_data);
	    CFRelease(label_data);
	}
	break;
    case kEAPOLClientItemIDTypeDefault: {
	CFDataRef		label_data;

	/* XXX localize? */
	label_data = my_CFDataCreateWithString(CFSTR("Default"));
	CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, label_data);
	CFRelease(label_data);
	break;
    }
    default:
	goto done;
    }
    
    /* Account */
    if (name != NULL) {
	CFDictionarySetValue(attrs, kEAPSecKeychainPropAccount, name);
    }
    
    /* Password */
    if (password != NULL) {
	CFDictionarySetValue(attrs, kEAPSecKeychainPropPassword, password);
    };

    if (domain == kEAPOLClientDomainUser) {
	CFArrayRef			trusted_apps;

	/* Trusted Applications */
	trusted_apps = copy_trusted_applications(FALSE);
	if (trusted_apps != NULL) {
	    CFDictionarySetValue(attrs,
				 kEAPSecKeychainPropTrustedApplications,
				 trusted_apps);
	    CFRelease(trusted_apps);
	}
    }
    else {
	CFDictionarySetValue(attrs,
			     kEAPSecKeychainPropAllowRootAccess,
			     kCFBooleanTrue);
    }
    unique_string = EAPOLClientItemIDCopyUniqueString(itemID, domain, TRUE);
    status = EAPSecKeychainPasswordItemSet2(keychain, unique_string,
					    attrs);
    if (status == errSecItemNotFound) {
	status = EAPSecKeychainPasswordItemCreate(keychain,
						  unique_string,
						  attrs);
    }
    my_CFRelease(&unique_string);
    if (status != noErr) {
	EAPLOG(LOG_NOTICE,
	       "EAPOLClientItemID: failed to set keychain item, %d",
	       (int)status);
    }

 done:
    my_CFRelease(&attrs);
    my_CFRelease(&keychain);
    return (status == noErr);
}
Пример #5
0
STATIC CFStringRef
EAPOLClientItemIDCopyUniqueString(EAPOLClientItemIDRef itemID,
				  EAPOLClientDomain domain, bool is_item)
{
    const char *	domain_str;
    CFStringRef		result = NULL;
    CFStringRef		profileID;
    CFDataRef		ssid;
    CFStringRef		ssid_str;
    const char *	type_str;

    type_str = is_item ? "item" : "identity";
    domain_str = (domain == kEAPOLClientDomainSystem) ? "system" : "user";
    switch (itemID->type) {
    case kEAPOLClientItemIDTypeWLANSSID:
	ssid_str = my_CFStringCreateWithData(itemID->u.ssid);
	result = create_item_format(domain_str, type_str, WLAN_SSID_STR,
				    ssid_str);
	if (ssid_str != NULL) {
	    CFRelease(ssid_str);
	}
	break;
    case kEAPOLClientItemIDTypeWLANDomain:
	result = create_item_format(domain_str, type_str,
				    WLAN_DOMAIN_STR, itemID->u.domain);
	break;
    case kEAPOLClientItemIDTypeProfileID:
	result = create_item_format(domain_str, type_str, PROFILEID_STR,
				    itemID->u.profileID);
	break;
    case kEAPOLClientItemIDTypeProfile:
	ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(itemID->u.profile,
							    NULL);
	if (ssid != NULL) {
	    ssid_str = my_CFStringCreateWithData(ssid);
	    result = create_item_format(domain_str, type_str, WLAN_SSID_STR,
					ssid_str);
	    if (ssid_str != NULL) {
		CFRelease(ssid_str);
	    }
	}
	else {
	    CFStringRef		wlan_domain;

	    wlan_domain = EAPOLClientProfileGetWLANDomain(itemID->u.profile);
	    if (wlan_domain != NULL) {
		result = create_item_format(domain_str, type_str,
					    WLAN_DOMAIN_STR, wlan_domain);
	    }
	    else {
		profileID = EAPOLClientProfileGetID(itemID->u.profile);
		result = create_item_format(domain_str, type_str, PROFILEID_STR,
					    profileID);
	    }
	}
	break;
    case kEAPOLClientItemIDTypeDefault:
	result = create_item_format(domain_str, type_str, DEFAULT_STR, NULL);
	break;
    default:
	break;
    }
    return (result);
}
Пример #6
0
STATIC void
import_profiles(EAPOLClientConfigurationRef cfg)
{
    int					count = 0;
    CFMutableDictionaryRef		domains_dict;
    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);
    domains_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;
    }

    /* allocate a single array, half for keys, half for values */
    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);
	}
	else {
	    CFStringRef		domain;

	    domain = EAPOLClientProfileGetWLANDomain(profile);
	    if (domain != NULL) {
		CFStringRef		conflicting_profileID;

		conflicting_profileID 
		    = CFDictionaryGetValue(profiles_dict, domain);
		if (conflicting_profileID != NULL) {
		    SCLog(TRUE, LOG_NOTICE, 
			  CFSTR("EAPOLClientConfiguration: ignoring profile %@:"
				" WLAN domain '%@' already used by %@"),
			  profileID, domain, conflicting_profileID);
		    CFRelease(profile);
		    continue;
		}
		CFDictionarySetValue(domains_dict, domain, profileID);
	    }
	}
	CFDictionarySetValue(profiles_dict, profileID, profile);
	EAPOLClientProfileSetConfiguration(profile, cfg);
	CFRelease(profile);
    }
    free(keys);

 done:
    cfg->ssids = ssids_dict;
    cfg->profiles = profiles_dict;
    cfg->domains = domains_dict;
    return;
}