1/* 2 * Copyright (c) 2009-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * EAPOLClientProfile.c 26 * - implementation of the EAPOLClientProfile CF object 27 */ 28 29/* 30 * Modification History 31 * 32 * December 8, 2009 Dieter Siegmund (dieter@apple.com) 33 * - created 34 */ 35 36#include <stdio.h> 37#include <stdlib.h> 38#include <unistd.h> 39#include <sys/types.h> 40#include <string.h> 41#include <TargetConditionals.h> 42#include <SystemConfiguration/SCPrivate.h> 43#include <SystemConfiguration/SCValidation.h> 44#include <pthread.h> 45#include "EAPClientProperties.h" 46#include "EAPOLClientConfigurationInternal.h" 47#include "symbol_scope.h" 48#include "myCFUtil.h" 49 50/** 51 ** Schema keys 52 **/ 53#define kProfileKeyProfileID CFSTR("ProfileID") 54#define kProfileKeyUserDefinedName CFSTR("UserDefinedName") 55#define kProfileKeyAuthenticationProperties CFSTR("AuthenticationProperties") 56#define kProfileKeyInformation CFSTR("Information") 57#define kProfileKeyWLAN CFSTR("WLAN") 58#define kProfileKeyWLANSSID CFSTR("SSID") 59#define kProfileKeyWLANSecurityType CFSTR("SecurityType") 60#define kProfileKeyWLANDomain CFSTR("Domain") 61 62/** 63 ** Utility Functions 64 **/ 65 66PRIVATE_EXTERN Boolean 67accept_types_valid(CFArrayRef accept) 68{ 69 int count; 70 int i; 71 72 if (isA_CFArray(accept) == NULL) { 73 return (FALSE); 74 } 75 count = CFArrayGetCount(accept); 76 if (count == 0) { 77 return (FALSE); 78 } 79 for (i = 0; i < count; i++) { 80 CFNumberRef type = CFArrayGetValueAtIndex(accept, i); 81 82 if (isA_CFNumber(type) == NULL) { 83 return (FALSE); 84 } 85 } 86 return (TRUE); 87} 88 89STATIC Boolean 90applicationID_is_valid(CFStringRef applicationID) 91{ 92 CFRange r; 93 94 if (CFStringGetLength(applicationID) < 3) { 95 return (FALSE); 96 } 97 r = CFStringFind(applicationID, CFSTR("."), 0); 98 if (r.location == kCFNotFound) { 99 return (FALSE); 100 } 101 return (TRUE); 102} 103 104/** 105 ** CF object glue code 106 **/ 107STATIC CFStringRef __EAPOLClientProfileCopyDebugDesc(CFTypeRef cf); 108STATIC void __EAPOLClientProfileDeallocate(CFTypeRef cf); 109STATIC Boolean __EAPOLClientProfileEqual(CFTypeRef cf1, CFTypeRef cf2); 110STATIC CFHashCode __EAPOLClientProfileHash(CFTypeRef cf); 111 112STATIC CFTypeID __kEAPOLClientProfileTypeID = _kCFRuntimeNotATypeID; 113 114STATIC const CFRuntimeClass __EAPOLClientProfileClass = { 115 0, /* version */ 116 "EAPOLClientProfile", /* className */ 117 NULL, /* init */ 118 NULL, /* copy */ 119 __EAPOLClientProfileDeallocate, /* deallocate */ 120 __EAPOLClientProfileEqual, /* equal */ 121 __EAPOLClientProfileHash, /* hash */ 122 NULL, /* copyFormattingDesc */ 123 __EAPOLClientProfileCopyDebugDesc /* copyDebugDesc */ 124}; 125 126STATIC CFStringRef 127__EAPOLClientProfileCopyDebugDesc(CFTypeRef cf) 128{ 129 CFAllocatorRef allocator = CFGetAllocator(cf); 130 EAPOLClientProfileRef profile = (EAPOLClientProfileRef)cf; 131 CFMutableStringRef result; 132 133 result = CFStringCreateMutable(allocator, 0); 134 CFStringAppendFormat(result, NULL, 135 CFSTR("<EAPOLClientProfile %p [%p]> {"), 136 cf, allocator); 137 138 CFStringAppendFormat(result, NULL, 139 CFSTR("ProfileID = %@"), 140 profile->uuid); 141 if (profile->user_defined_name != NULL) { 142 CFStringAppendFormat(result, NULL, 143 CFSTR(" Name = '%@'"), 144 profile->user_defined_name); 145 } 146 if (profile->WLAN.ssid != NULL) { 147 CFStringRef ssid_str = my_CFStringCreateWithData(profile->WLAN.ssid); 148 149 CFStringAppendFormat(result, NULL, 150 CFSTR(", WLAN SSID %@ [%@]"), 151 ssid_str, profile->WLAN.security_type); 152 CFRelease(ssid_str); 153 } 154 if (profile->auth_props != NULL) { 155 CFStringAppendFormat(result, NULL, 156 CFSTR(", auth_props = %@"), 157 profile->auth_props); 158 } 159 if (profile->information != NULL 160 && CFDictionaryGetCount(profile->information) != 0) { 161 CFStringAppendFormat(result, NULL, 162 CFSTR(", info = %@"), 163 profile->information); 164 } 165 CFStringAppendFormat(result, NULL, CFSTR("}")); 166 return result; 167} 168 169 170STATIC void 171__EAPOLClientProfileDeallocate(CFTypeRef cf) 172{ 173 EAPOLClientProfileRef profile = (EAPOLClientProfileRef)cf; 174 175 my_CFRelease(&profile->uuid); 176 my_CFRelease(&profile->auth_props); 177 my_CFRelease(&profile->user_defined_name); 178 my_CFRelease(&profile->WLAN.ssid); 179 my_CFRelease(&profile->WLAN.security_type); 180 my_CFRelease(&profile->information); 181 return; 182} 183 184 185STATIC Boolean 186__EAPOLClientProfileEqual(CFTypeRef cf1, CFTypeRef cf2) 187{ 188 EAPOLClientProfileRef prof1 = (EAPOLClientProfileRef)cf1; 189 EAPOLClientProfileRef prof2 = (EAPOLClientProfileRef)cf2; 190 191 if (CFEqual(prof1->uuid, prof2->uuid) == FALSE) { 192 return (FALSE); 193 } 194 if (my_CFEqual(prof1->auth_props, prof2->auth_props) == FALSE) { 195 return (FALSE); 196 } 197 if (my_CFEqual(prof1->user_defined_name, 198 prof2->user_defined_name) == FALSE) { 199 return (FALSE); 200 } 201 if (my_CFEqual(prof1->WLAN.ssid, prof2->WLAN.ssid) == FALSE) { 202 return (FALSE); 203 } 204 if (my_CFEqual(prof1->WLAN.security_type, prof2->WLAN.security_type) 205 == FALSE) { 206 return (FALSE); 207 } 208 if (my_CFEqual(prof1->information, prof2->information) == FALSE) { 209 return (FALSE); 210 } 211 return (TRUE); 212} 213 214STATIC CFHashCode 215__EAPOLClientProfileHash(CFTypeRef cf) 216{ 217 EAPOLClientProfileRef profile = (EAPOLClientProfileRef)cf; 218 219 return (CFHash(profile->uuid)); 220} 221 222 223STATIC void 224__EAPOLClientProfileInitialize(void) 225{ 226 /* initialize runtime */ 227 __kEAPOLClientProfileTypeID 228 = _CFRuntimeRegisterClass(&__EAPOLClientProfileClass); 229 return; 230} 231 232STATIC void 233__EAPOLClientProfileRegisterClass(void) 234{ 235 STATIC pthread_once_t initialized = PTHREAD_ONCE_INIT; 236 237 pthread_once(&initialized, __EAPOLClientProfileInitialize); 238 return; 239} 240 241STATIC EAPOLClientProfileRef 242__EAPOLClientProfileAllocate(CFAllocatorRef allocator) 243{ 244 EAPOLClientProfileRef profile; 245 int size; 246 247 __EAPOLClientProfileRegisterClass(); 248 249 size = sizeof(*profile) - sizeof(CFRuntimeBase); 250 profile = (EAPOLClientProfileRef) 251 _CFRuntimeCreateInstance(allocator, 252 __kEAPOLClientProfileTypeID, size, NULL); 253 bzero(((void *)profile) + sizeof(CFRuntimeBase), size); 254 return (profile); 255} 256 257/** 258 ** EAPOLClientProfile APIs 259 **/ 260 261CFTypeID 262EAPOLClientProfileGetTypeID(void) 263{ 264 __EAPOLClientProfileRegisterClass(); 265 return (__kEAPOLClientProfileTypeID); 266} 267 268/* 269 * Function: EAPOLClientProfileCreate 270 * 271 * Purpose: 272 * Instantiate a new profile to be filled in by calling the various 273 * "setter" functions: 274 * EAPOLClientProfileSetUserDefinedName 275 * EAPOLClientProfileSetAuthenticationProperties 276 * EAPOLClientProfileSetWLANSSIDAndSecurityType 277 * EAPOLClientProfileSetWLANDomain 278 * EAPOLClientProfileSetInformation 279 * 280 */ 281EAPOLClientProfileRef 282EAPOLClientProfileCreate(EAPOLClientConfigurationRef cfg) 283{ 284 CFAllocatorRef alloc = CFGetAllocator(cfg); 285 EAPOLClientProfileRef profile; 286 287 profile = __EAPOLClientProfileAllocate(alloc); 288 if (profile == NULL) { 289 return (NULL); 290 } 291 profile->uuid = my_CFUUIDStringCreate(alloc); 292 if (EAPOLClientConfigurationAddProfile(cfg, profile) == FALSE) { 293 /* this should not happen */ 294 my_CFRelease(&profile); 295 } 296 return (profile); 297} 298 299/* 300 * Function: EAPOLClientProfileGetUserDefinedName 301 * 302 * Purpose: 303 * Retrieve the user defined string associated with the profile. 304 * 305 * Returns: 306 * NULL if no user defined name is set, non-NULL otherwise. 307 */ 308CFStringRef 309EAPOLClientProfileGetUserDefinedName(EAPOLClientProfileRef profile) 310{ 311 return (profile->user_defined_name); 312} 313 314 315/* 316 * Function: EAPOLClientProfileGetUserDefinedName 317 * 318 * Purpose: 319 * Set the user defined string associated with the profile. 320 * 321 * Notes: 322 * If user_defined_name is NULL, the user visible name is removed, 323 * otherwise it is set to the value passed. 324 */ 325void 326EAPOLClientProfileSetUserDefinedName(EAPOLClientProfileRef profile, 327 CFStringRef user_defined_name) 328{ 329 if (user_defined_name != NULL) { 330 CFRetain(user_defined_name); 331 } 332 if (profile->user_defined_name != NULL) { 333 CFRelease(profile->user_defined_name); 334 } 335 profile->user_defined_name = user_defined_name; 336 return; 337} 338 339/* 340 * Function: EAPOLClientProfileGetID 341 * 342 * Purpose: 343 * Get the unique identifier for the profile. 344 */ 345CFStringRef 346EAPOLClientProfileGetID(EAPOLClientProfileRef profile) 347{ 348 return (profile->uuid); 349} 350 351/* 352 * Function: EAPOLClientProfileGetAuthenticationProperties 353 * 354 * Purpose: 355 * Returns the EAP client authentication properties for the profile. 356 * The individual keys in the dictionary are defined in 357 * <EAP8021X/EAPClientProperties.h>. 358 */ 359CFDictionaryRef 360EAPOLClientProfileGetAuthenticationProperties(EAPOLClientProfileRef profile) 361{ 362 return (profile->auth_props); 363} 364 365/* 366 * Function: EAPOLClientProfileSetAuthenticationProperties 367 * Purpose: 368 * Set the EAP client authentication properties for the profile. 369 * The individual keys in the dictionary are defined in 370 * <EAP8021X/EAPClientProperties.h>. 371 */ 372void 373EAPOLClientProfileSetAuthenticationProperties(EAPOLClientProfileRef profile, 374 CFDictionaryRef auth_props) 375{ 376 if (auth_props != NULL) { 377 CFRetain(auth_props); 378 } 379 if (profile->auth_props != NULL) { 380 CFRelease(profile->auth_props); 381 } 382 profile->auth_props = auth_props; 383 return; 384} 385 386/* 387 * Function: EAPOLClientProfileGetWLANSSIDAndSecurityType 388 * 389 * Purpose: 390 * Get the SSID and security type associated with the profile. 391 * 392 * Returns: 393 * non-NULL SSID and security type if the profile is bound to a WLAN SSID, 394 * NULL otherwise. 395 */ 396CFDataRef 397EAPOLClientProfileGetWLANSSIDAndSecurityType(EAPOLClientProfileRef profile, 398 CFStringRef * ret_security_type) 399{ 400 if (profile->WLAN.ssid != NULL) { 401 if (ret_security_type != NULL) { 402 *ret_security_type = profile->WLAN.security_type; 403 } 404 return (profile->WLAN.ssid); 405 } 406 if (ret_security_type != NULL) { 407 *ret_security_type = NULL; 408 } 409 return (NULL); 410} 411 412/* 413 * Function: EAPOLClientProfileSetWLANSSIDAndSecurityType 414 * 415 * Purpose: 416 * Bind the profile to a particular SSID, and specify the expected 417 * security type i.e. WEP, WPA, WPA2 or any. Only a single profile can be 418 * associated with a particular SSID. 419 * 420 * To un-bind the profile from its SSID, set the ssid argument to NULL. 421 * In that case, the security_type argument will be ignored. 422 * 423 * Returns: 424 * FALSE if there's an existing profile with the same SSID, or the 425 * security_type is not one of the defined strings above, 426 * TRUE otherwise. 427 */ 428Boolean 429EAPOLClientProfileSetWLANSSIDAndSecurityType(EAPOLClientProfileRef profile, 430 CFDataRef ssid, 431 CFStringRef security_type) 432{ 433 EAPOLClientProfileRef existing_profile; 434 435 if (ssid != NULL) { 436 if (profile->WLAN.domain != NULL) { 437 /* can't specify an SSID when domain is already specified */ 438 return (FALSE); 439 } 440 if (security_type == NULL) { 441 /* both SSID and security_type must be specified */ 442 return (FALSE); 443 } 444 if (profile->cfg != NULL) { 445 existing_profile 446 = EAPOLClientConfigurationGetProfileWithWLANSSID(profile->cfg, 447 ssid); 448 if (existing_profile != NULL && existing_profile != profile) { 449 /* some other profile has this SSID already */ 450 return (FALSE); 451 } 452 } 453 } 454 else if (security_type != NULL) { 455 /* SSID is NULL, so security_type must also be NULL */ 456 return (FALSE); 457 } 458 459 /* give up the existing SSID */ 460 if (profile->WLAN.ssid != NULL && profile->cfg != NULL) { 461 /* clear the old binding */ 462 EAPOLClientConfigurationSetProfileForSSID(profile->cfg, 463 profile->WLAN.ssid, 464 NULL); 465 } 466 467 /* claim the new SSID */ 468 if (ssid != NULL) { 469 CFRetain(ssid); 470 if (profile->cfg != NULL) { 471 EAPOLClientConfigurationSetProfileForSSID(profile->cfg, 472 ssid, 473 profile); 474 } 475 } 476 if (security_type != NULL) { 477 CFRetain(security_type); 478 } 479 if (profile->WLAN.ssid != NULL) { 480 CFRelease(profile->WLAN.ssid); 481 } 482 if (profile->WLAN.security_type != NULL) { 483 CFRelease(profile->WLAN.security_type); 484 } 485 profile->WLAN.ssid = ssid; 486 profile->WLAN.security_type = security_type; 487 return (TRUE); 488} 489 490/* 491 * Function: EAPOLClientProfileGetWLANDomain 492 * 493 * Purpose: 494 * Get the WLAN Hotspot 2.0 domain name associated with the profile. 495 * 496 * Returns: 497 * non-NULL domain name if the profile is bound to a Hotspot 2.0 WLAN 498 * domain name, NULL otherwise. 499 */ 500CFStringRef 501EAPOLClientProfileGetWLANDomain(EAPOLClientProfileRef profile) 502{ 503 return (profile->WLAN.domain); 504} 505 506/* 507 * Function: EAPOLClientProfileSetWLANDomain 508 * 509 * Purpose: 510 * Bind the profile to a Hotspot 2.0 domain name. 511 * 512 * Only a single profile can be associated with a particular domain name. 513 * 514 * To un-bind the profile from the domain name, set the domain 515 * argument to NULL. 516 * 517 * Returns: 518 * FALSE if there's an existing profile with the same domain name, 519 * TRUE otherwise. 520 * 521 * Note: 522 * EAPOLClientProfileSetWLANSSIDAndSecurityType() and 523 * EAPOLClientProfileSetWLANDomain() are mutally exclusive. 524 * A given profile can only be associated with a WLAN SSID *or* a 525 * WLAN domain and not both. 526 */ 527Boolean 528EAPOLClientProfileSetWLANDomain(EAPOLClientProfileRef profile, 529 CFStringRef domain) 530{ 531 EAPOLClientProfileRef existing_profile; 532 533 if (domain != NULL) { 534 if (profile->WLAN.ssid != NULL) { 535 /* can't specify a domain when ssid is already specified */ 536 return (FALSE); 537 } 538 if (profile->cfg != NULL) { 539 existing_profile 540 = EAPOLClientConfigurationGetProfileWithWLANDomain(profile->cfg, 541 domain); 542 if (existing_profile != NULL && existing_profile != profile) { 543 /* some other profile has this domain already */ 544 return (FALSE); 545 } 546 } 547 } 548 549 /* give up the existing domain */ 550 if (profile->WLAN.domain != NULL && profile->cfg != NULL) { 551 /* clear the old binding */ 552 EAPOLClientConfigurationSetProfileForWLANDomain(profile->cfg, 553 profile->WLAN.domain, 554 NULL); 555 } 556 557 /* claim the domain */ 558 if (domain != NULL) { 559 CFRetain(domain); 560 if (profile->cfg != NULL) { 561 EAPOLClientConfigurationSetProfileForWLANDomain(profile->cfg, 562 domain, 563 profile); 564 } 565 } 566 if (profile->WLAN.domain != NULL) { 567 CFRelease(profile->WLAN.domain); 568 } 569 profile->WLAN.domain = domain; 570 return (TRUE); 571} 572 573/* 574 * Function: EAPOLClientProfileSetInformation 575 * 576 * Purpose: 577 * Associate additional information with the profile using the given 578 * application identifier. 579 * 580 * If info is NULL, the information for the particular application is cleared. 581 * 582 * Note: 583 * applicationID must be an application identifier e.g. "com.mycompany.myapp". 584 */ 585Boolean 586EAPOLClientProfileSetInformation(EAPOLClientProfileRef profile, 587 CFStringRef applicationID, 588 CFDictionaryRef information) 589{ 590 if (applicationID_is_valid(applicationID) == FALSE) { 591 return (FALSE); 592 } 593 if (information == NULL) { 594 if (profile->information != NULL) { 595 CFDictionaryRemoveValue(profile->information, applicationID); 596 } 597 } 598 else { 599 if (isA_CFDictionary(information) == NULL) { 600 return (FALSE); 601 } 602 if (profile->information == NULL) { 603 profile->information 604 = CFDictionaryCreateMutable(NULL, 0, 605 &kCFTypeDictionaryKeyCallBacks, 606 &kCFTypeDictionaryValueCallBacks); 607 } 608 CFDictionarySetValue(profile->information, applicationID, information); 609 } 610 return (TRUE); 611} 612 613/* 614 * Function: EAPOLClientProfileGetInformation 615 * 616 * Purpose: 617 * Retrieve the additional information associated with the profile using 618 * the given application identifier. 619 * 620 * Returns: 621 * NULL if no such application identifier exists, 622 * non-NULL dictionary otherwise. 623 * 624 * Note: 625 * applicationID must be an application identifier e.g. "com.mycompany.myapp". 626 */ 627CFDictionaryRef 628EAPOLClientProfileGetInformation(EAPOLClientProfileRef profile, 629 CFStringRef applicationID) 630{ 631 CFDictionaryRef dict; 632 633 if (profile->information == NULL) { 634 return (NULL); 635 } 636 if (applicationID_is_valid(applicationID) == FALSE) { 637 return (NULL); 638 } 639 dict = CFDictionaryGetValue(profile->information, applicationID); 640 return (isA_CFDictionary(dict)); 641} 642 643/* 644 * Function: EAPOLClientProfileCreatePropertyList 645 * 646 * Purpose: 647 * Create an "external" format for a profile. 648 * 649 * Returns: 650 * NULL if the profile could not be externalized, non-NULL otherwise. 651 */ 652CFPropertyListRef 653EAPOLClientProfileCreatePropertyList(EAPOLClientProfileRef profile) 654{ 655 CFMutableDictionaryRef dict; 656 CFStringRef profileID; 657 658 dict = EAPOLClientProfileCreateDictAndProfileID(profile, &profileID); 659 if (dict == NULL) { 660 return (NULL); 661 } 662 CFDictionarySetValue(dict, kProfileKeyProfileID, profileID); 663 return ((CFPropertyListRef)dict); 664} 665 666/* 667 * Function: EAPOLClientProfileCreateWithPropertyList 668 * 669 * Purpose: 670 * Create a profile using the supplied "external_format". The profile 671 * is not tied to the configuration until the function 672 * EAPOLClientConfigurationAddProfile() is invoked successfully. 673 * Use EAPOLClientConfigurationGetMatchingProfiles() to check for conflicts 674 * if calling that function fails. 675 * 676 * Returns: 677 * NULL if the "external_format" property list was not a valid format, 678 * non-NULL EAPOLClientProfileRef otherwise. 679 */ 680EAPOLClientProfileRef 681EAPOLClientProfileCreateWithPropertyList(CFPropertyListRef external_format) 682{ 683 CFDictionaryRef dict = (CFDictionaryRef)external_format; 684 CFStringRef profileID; 685 686 if (isA_CFDictionary(dict) == NULL) { 687 return (NULL); 688 } 689 profileID = CFDictionaryGetValue(dict, kProfileKeyProfileID); 690 if (isA_CFString(profileID) == NULL) { 691 return (NULL); 692 } 693 return (EAPOLClientProfileCreateWithDictAndProfileID(dict, profileID)); 694} 695 696/** 697 ** Internal API 698 **/ 699 700PRIVATE_EXTERN CFMutableDictionaryRef 701EAPOLClientProfileCreateDictAndProfileID(EAPOLClientProfileRef profile, 702 CFStringRef * ret_profileID) 703{ 704 CFArrayRef accept_types = NULL; 705 CFMutableDictionaryRef dict; 706 707 if (profile->auth_props != NULL) { 708 accept_types = CFDictionaryGetValue(profile->auth_props, 709 kEAPClientPropAcceptEAPTypes); 710 } 711 if (accept_types_valid(accept_types) == FALSE) { 712 SCLog(TRUE, LOG_NOTICE, 713 CFSTR("EAPOLClientConfiguration: profile %@" 714 " missing/invalid AuthenticationProperties"), 715 EAPOLClientProfileGetID(profile)); 716 return (NULL); 717 } 718 dict = CFDictionaryCreateMutable(NULL, 0, 719 &kCFTypeDictionaryKeyCallBacks, 720 &kCFTypeDictionaryValueCallBacks); 721 if (ret_profileID != NULL) { 722 *ret_profileID = CFRetain(profile->uuid); 723 } 724 CFDictionarySetValue(dict, 725 kProfileKeyAuthenticationProperties, 726 profile->auth_props); 727 if (profile->user_defined_name != NULL) { 728 CFDictionarySetValue(dict, 729 kProfileKeyUserDefinedName, 730 profile->user_defined_name); 731 } 732 if (profile->information != NULL 733 && CFDictionaryGetCount(profile->information) != 0) { 734 CFDictionarySetValue(dict, 735 kProfileKeyInformation, 736 profile->information); 737 } 738 if (profile->WLAN.ssid != NULL || profile->WLAN.domain != NULL) { 739 int count; 740 const void * keys[2]; 741 CFDictionaryRef WLAN; 742 const void * values[2]; 743 744 if (profile->WLAN.ssid != NULL) { 745 keys[0] = kProfileKeyWLANSSID; 746 values[0] = profile->WLAN.ssid; 747 keys[1] = kProfileKeyWLANSecurityType; 748 values[1] = profile->WLAN.security_type; 749 count = 2; 750 } 751 else { 752 keys[0] = kProfileKeyWLANDomain; 753 values[0] = profile->WLAN.domain; 754 count = 1; 755 } 756 WLAN = CFDictionaryCreate(NULL, keys, values, count, 757 &kCFTypeDictionaryKeyCallBacks, 758 &kCFTypeDictionaryValueCallBacks); 759 CFDictionarySetValue(dict, kProfileKeyWLAN, WLAN); 760 CFRelease(WLAN); 761 } 762 return (dict); 763} 764 765PRIVATE_EXTERN EAPOLClientProfileRef 766EAPOLClientProfileCreateWithDictAndProfileID(CFDictionaryRef dict, 767 CFStringRef profileID) 768{ 769 CFAllocatorRef alloc = CFGetAllocator(dict); 770 CFArrayRef accept_types; 771 CFDictionaryRef information; 772 CFStringRef domain = NULL; 773 CFDictionaryRef eap_config; 774 EAPOLClientProfileRef profile; 775 CFStringRef security_type = NULL; 776 CFStringRef user_defined_name; 777 CFDataRef ssid = NULL; 778 CFDictionaryRef wlan; 779 780 eap_config = CFDictionaryGetValue(dict, 781 kProfileKeyAuthenticationProperties); 782 if (isA_CFDictionary(eap_config) == NULL 783 || CFDictionaryGetCount(eap_config) == 0) { 784 SCLog(TRUE, LOG_NOTICE, 785 CFSTR("EAPOLClientConfiguration: profile %@" 786 " missing/invalid %@ property"), 787 profileID, kProfileKeyAuthenticationProperties); 788 return (NULL); 789 } 790 accept_types = CFDictionaryGetValue(eap_config, 791 kEAPClientPropAcceptEAPTypes); 792 if (accept_types_valid(accept_types) == FALSE) { 793 SCLog(TRUE, LOG_NOTICE, 794 CFSTR("EAPOLClientConfiguration: profile %@" 795 " missing/invalid %@ property in %@"), 796 profileID, kEAPClientPropAcceptEAPTypes, 797 kProfileKeyAuthenticationProperties); 798 return (NULL); 799 } 800 wlan = CFDictionaryGetValue(dict, kProfileKeyWLAN); 801 if (wlan != NULL) { 802 if (isA_CFDictionary(wlan) == NULL) { 803 SCLog(TRUE, LOG_NOTICE, 804 CFSTR("EAPOLClientConfiguration: profile %@" 805 " invalid %@ property"), 806 profileID, kProfileKeyWLAN); 807 return (NULL); 808 } 809 ssid = CFDictionaryGetValue(wlan, kProfileKeyWLANSSID); 810 domain = CFDictionaryGetValue(wlan, kProfileKeyWLANDomain); 811 if (isA_CFData(ssid) == NULL && isA_CFString(domain) == NULL) { 812 SCLog(TRUE, LOG_NOTICE, 813 CFSTR("EAPOLClientConfiguration: profile %@" 814 " invalid/missing property (%@ or %@) in %@"), 815 profileID, kProfileKeyWLANSSID, kProfileKeyWLANDomain, 816 kProfileKeyWLAN); 817 return (NULL); 818 } 819 if (ssid != NULL) { 820 security_type = CFDictionaryGetValue(wlan, 821 kProfileKeyWLANSecurityType); 822 if (isA_CFString(security_type) == NULL) { 823 SCLog(TRUE, LOG_NOTICE, 824 CFSTR("EAPOLClientConfiguration: profile %@" 825 " invalid/missing %@ property in %@"), 826 profileID, kProfileKeyWLANSecurityType, kProfileKeyWLAN); 827 return (NULL); 828 } 829 } 830 } 831 user_defined_name = CFDictionaryGetValue(dict, kProfileKeyUserDefinedName); 832 if (user_defined_name != NULL && isA_CFString(user_defined_name) == NULL) { 833 SCLog(TRUE, LOG_NOTICE, 834 CFSTR("EAPOLClientConfiguration: profile %@" 835 " invalid %@ property"), 836 profileID, kProfileKeyUserDefinedName); 837 return (NULL); 838 } 839 information = CFDictionaryGetValue(dict, kProfileKeyInformation); 840 if (information != NULL && isA_CFDictionary(information) == NULL) { 841 SCLog(TRUE, LOG_NOTICE, 842 CFSTR("EAPOLClientConfiguration: profile %@" 843 " invalid %@ property"), 844 profileID, kProfileKeyInformation); 845 return (NULL); 846 } 847 848 /* allocate/set an EAPOLClientProfileRef */ 849 profile = __EAPOLClientProfileAllocate(alloc); 850 if (profile == NULL) { 851 return (NULL); 852 } 853 profile->uuid = CFRetain(profileID); 854 EAPOLClientProfileSetUserDefinedName(profile, user_defined_name); 855 EAPOLClientProfileSetAuthenticationProperties(profile, eap_config); 856 if (ssid != NULL) { 857 EAPOLClientProfileSetWLANSSIDAndSecurityType(profile, ssid, 858 security_type); 859 } 860 else if (domain != NULL) { 861 EAPOLClientProfileSetWLANDomain(profile, domain); 862 } 863 if (information != NULL) { 864 profile->information 865 = CFDictionaryCreateMutableCopy(NULL, 0, information); 866 } 867 return (profile); 868} 869 870PRIVATE_EXTERN void 871EAPOLClientProfileSetConfiguration(EAPOLClientProfileRef profile, 872 EAPOLClientConfigurationRef cfg) 873{ 874 /* we can't retain the configuration, since it retains us */ 875 profile->cfg = cfg; 876 return; 877} 878 879PRIVATE_EXTERN EAPOLClientConfigurationRef 880EAPOLClientProfileGetConfiguration(EAPOLClientProfileRef profile) 881{ 882 return (profile->cfg); 883} 884