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 * EAPOLClientItemID.c 26 * - implementation of the EAPOLClientItemID CF object 27 */ 28 29/* 30 * Modification History 31 * 32 * December 2, 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 <sys/param.h> 41#include <string.h> 42#include <syslog.h> 43#include <servers/bootstrap.h> 44#include <bootstrap_priv.h> 45#include <TargetConditionals.h> 46#include <CoreFoundation/CFString.h> 47#include <Security/SecIdentity.h> 48#include <Security/SecIdentityPriv.h> 49#include <Security/SecTrustedApplication.h> 50#include <Security/SecTrustedApplicationPriv.h> 51#include <SystemConfiguration/SCValidation.h> 52#include <pthread.h> 53#include <mach/mach_init.h> 54#include <mach/vm_map.h> 55#include "EAPCertificateUtil.h" 56#include "EAPOLClientConfigurationInternal.h" 57#include "EAPOLClientConfigurationPrivate.h" 58#include "EAPSecurity.h" 59#include "EAPKeychainUtil.h" 60#include "EAPKeychainUtilInternal.h" 61#include "eapolcfg_auth.h" 62#include "symbol_scope.h" 63#include "myCFUtil.h" 64#include "EAPLog.h" 65 66/** 67 ** Utility functions 68 **/ 69STATIC CFTypeRef 70my_CFDictionaryCopyValue(CFDictionaryRef dict, CFStringRef key) 71{ 72 CFTypeRef value; 73 74 value = CFDictionaryGetValue(dict, key); 75 if (value != NULL) { 76 CFRetain(value); 77 } 78 return (value); 79} 80 81#define kEAPOLControllerPath "/System/Library/SystemConfiguration/EAPOLController.bundle" 82#define keapolclientPath "eapolclient" 83#define kAirPortApplicationGroup "AirPort" 84#define kSystemUIServerPath "/System/Library/CoreServices/SystemUIServer.app" 85 86STATIC SecTrustedApplicationRef 87create_trusted_app_from_bundle_resource(CFStringRef bundle_path, 88 CFStringRef resource_path) 89{ 90 CFBundleRef bundle; 91 CFURLRef bundle_url; 92 CFURLRef eapolclient_url = NULL; 93 char path[MAXPATHLEN]; 94 Boolean success = FALSE; 95 SecTrustedApplicationRef trusted_app = NULL; 96 97 bundle_url = CFURLCreateWithFileSystemPath(NULL, 98 bundle_path, 99 kCFURLPOSIXPathStyle, FALSE); 100 if (bundle_url == NULL) { 101 goto done; 102 } 103 bundle = CFBundleCreate(NULL, bundle_url); 104 CFRelease(bundle_url); 105 if (bundle == NULL) { 106 goto done; 107 } 108 eapolclient_url 109 = CFBundleCopyResourceURL(bundle, CFSTR(keapolclientPath), 110 NULL, NULL); 111 CFRelease(bundle); 112 if (eapolclient_url == NULL) { 113 goto done; 114 } 115 success = CFURLGetFileSystemRepresentation(eapolclient_url, 116 TRUE, 117 (UInt8 *)path, sizeof(path)); 118 CFRelease(eapolclient_url); 119 if (success) { 120 OSStatus status; 121 122 status = SecTrustedApplicationCreateFromPath(path, 123 &trusted_app); 124 if (status != noErr) { 125 fprintf(stderr, 126 "SecTrustedApplicationCreateFromPath(%s) failed, %d\n", 127 path, (int)status); 128 } 129 } 130 131 done: 132 return (trusted_app); 133} 134 135STATIC CFArrayRef 136copy_trusted_applications(bool eapolclient_only) 137{ 138 CFMutableArrayRef array; 139 SecTrustedApplicationRef trusted_app; 140 OSStatus status; 141 142 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 143 144 /* eapolclient */ 145 trusted_app 146 = create_trusted_app_from_bundle_resource(CFSTR(kEAPOLControllerPath), 147 CFSTR(keapolclientPath)); 148 if (trusted_app != NULL) { 149 CFArrayAppendValue(array, trusted_app); 150 CFRelease(trusted_app); 151 } 152 153 /* AirPort Application Group */ 154 status 155 = SecTrustedApplicationCreateApplicationGroup(kAirPortApplicationGroup, 156 NULL, &trusted_app); 157 if (status != noErr) { 158 fprintf(stderr, 159 "SecTrustedApplicationCreateApplicationGroup(" 160 kAirPortApplicationGroup ") failed, %d\n", 161 (int)status); 162 } 163 else { 164 CFArrayAppendValue(array, trusted_app); 165 CFRelease(trusted_app); 166 } 167 if (eapolclient_only) { 168 goto done; 169 } 170 171 /* this executable */ 172 status = SecTrustedApplicationCreateFromPath(NULL, &trusted_app); 173 if (status != noErr) { 174 fprintf(stderr, 175 "SecTrustedApplicationCreateFromPath(NULL) failed, %d\n", 176 (int)status); 177 } 178 else { 179 CFArrayAppendValue(array, trusted_app); 180 CFRelease(trusted_app); 181 } 182 183 /* SystemUIServer */ 184 status = SecTrustedApplicationCreateFromPath(kSystemUIServerPath, 185 &trusted_app); 186 if (status != noErr) { 187 fprintf(stderr, 188 "SecTrustedApplicationCreateFromPath(%s) failed, %d\n", 189 kSystemUIServerPath, 190 (int)status); 191 } 192 else { 193 CFArrayAppendValue(array, trusted_app); 194 CFRelease(trusted_app); 195 } 196 197 done: 198 if (CFArrayGetCount(array) == 0) { 199 my_CFRelease(&array); 200 } 201 return (array); 202} 203 204OSStatus 205EAPOLClientSetACLForIdentity(SecIdentityRef identity) 206{ 207 SecKeyRef private_key = NULL; 208 CFArrayRef trusted_apps = NULL; 209 OSStatus status; 210 211 status = SecIdentityCopyPrivateKey(identity, &private_key); 212 if (status != noErr) { 213 goto done; 214 } 215 trusted_apps = copy_trusted_applications(TRUE); 216 if (trusted_apps == NULL) { 217 status = errSecParam; 218 goto done; 219 } 220 status 221 = EAPSecKeychainItemSetAccessForTrustedApplications((SecKeychainItemRef) 222 private_key, 223 trusted_apps); 224 done: 225 my_CFRelease(&private_key); 226 my_CFRelease(&trusted_apps); 227 return (status); 228} 229 230STATIC CFDataRef 231itemID_copy_data(EAPOLClientItemIDRef itemID) 232{ 233 CFDataRef data; 234 CFDictionaryRef dict; 235 236 dict = EAPOLClientItemIDCopyDictionary(itemID); 237 data = CFPropertyListCreateXMLData(NULL, dict); 238 if (dict != NULL) { 239 CFRelease(dict); 240 } 241 return (data); 242} 243 244STATIC mach_port_t 245eapolcfg_auth_server_port(void) 246{ 247 kern_return_t kret; 248 mach_port_t server; 249 250#ifdef BOOTSTRAP_PRIVILEGED_SERVER 251 kret = bootstrap_look_up2(bootstrap_port, 252 EAPOLCFG_AUTH_SERVER, 253 &server, 254 0, 255 BOOTSTRAP_PRIVILEGED_SERVER); 256 257#else /* BOOTSTRAP_PRIVILEGED_SERVER */ 258 kret = bootstrap_look_up(bootstrap_port, EAPOLCFG_AUTH_SERVER, server_p); 259 260#endif /* BOOTSTRAP_PRIVILEGED_SERVER */ 261 262 if (kret != BOOTSTRAP_SUCCESS) { 263 /* just to make sure */ 264 server = MACH_PORT_NULL; 265 EAPLOG(LOG_NOTICE, "EAPOLClientItemID: can't lookup eapolcfg_auth"); 266 } 267 return (server); 268} 269 270/** 271 ** interface to eapolcfg_auth MiG routines 272 **/ 273STATIC Boolean 274authEAPOLClientItemIDSetIdentity(EAPOLClientItemIDRef itemID, 275 SecIdentityRef identity) 276{ 277 AuthorizationExternalForm * auth_ext_p; 278 CFDataRef id_data = NULL; 279 OOBData_t id_handle; 280 mach_msg_type_number_t id_handle_length; 281 CFDataRef itemID_data = NULL; 282 kern_return_t kret; 283 int result = ENXIO; 284 mach_port_t server; 285 286 server = eapolcfg_auth_server_port(); 287 if (server == MACH_PORT_NULL) { 288 return (FALSE); 289 } 290 auth_ext_p = EAPOLClientItemIDGetAuthorizationExternalForm(itemID); 291 if (identity != NULL) { 292 id_data = EAPSecIdentityHandleCreate(identity); 293 if (id_data == NULL) { 294 goto done; 295 } 296 id_handle = (OOBData_t)CFDataGetBytePtr(id_data); 297 id_handle_length = CFDataGetLength(id_data); 298 } 299 else { 300 id_handle = NULL; 301 id_handle_length = 0; 302 } 303 itemID_data = itemID_copy_data(itemID); 304 kret = eapolclientitemid_set_identity(server, 305 auth_ext_p->bytes, 306 sizeof(auth_ext_p->bytes), 307 (xmlData_t) 308 CFDataGetBytePtr(itemID_data), 309 CFDataGetLength(itemID_data), 310 id_handle, 311 id_handle_length, 312 &result); 313 if (kret != KERN_SUCCESS) { 314 EAPLOG(LOG_ERR, "eapolclientitemid_set_identity failed %d", 315 kret); 316 } 317 if (result != 0) { 318 EAPLOG(LOG_NOTICE, "eapolclientitemid_set_identity() returned %d", 319 result); 320 } 321 done: 322 my_CFRelease(&itemID_data); 323 my_CFRelease(&id_data); 324 return (result == 0); 325} 326 327STATIC Boolean 328authEAPOLClientItemIDSetPasswordItem(EAPOLClientItemIDRef itemID, 329 CFDataRef name_data, 330 CFDataRef password_data) 331{ 332 AuthorizationExternalForm * auth_ext_p; 333 CFDataRef itemID_data; 334 uint32_t flags = 0; 335 kern_return_t kret; 336 OOBData_t name; 337 mach_msg_type_number_t name_length; 338 OOBData_t password; 339 mach_msg_type_number_t password_length; 340 int result = ENXIO; 341 mach_port_t server; 342 343 server = eapolcfg_auth_server_port(); 344 if (server == MACH_PORT_NULL) { 345 return (FALSE); 346 } 347 auth_ext_p = EAPOLClientItemIDGetAuthorizationExternalForm(itemID); 348 if (name_data != NULL) { 349 flags |= keapolcfg_auth_set_name; 350 name = (OOBData_t)CFDataGetBytePtr(name_data); 351 name_length = CFDataGetLength(name_data); 352 } 353 else { 354 name = NULL; 355 name_length = 0; 356 } 357 if (password_data != NULL) { 358 flags |= keapolcfg_auth_set_password; 359 password = (OOBData_t)CFDataGetBytePtr(password_data); 360 password_length = CFDataGetLength(password_data); 361 } 362 else { 363 password = NULL; 364 password_length = 0; 365 } 366 itemID_data = itemID_copy_data(itemID); 367 kret = eapolclientitemid_set_password(server, 368 auth_ext_p->bytes, 369 sizeof(auth_ext_p->bytes), 370 (xmlData_t) 371 CFDataGetBytePtr(itemID_data), 372 CFDataGetLength(itemID_data), 373 flags, 374 name, name_length, 375 password, password_length, 376 &result); 377 if (kret != KERN_SUCCESS) { 378 EAPLOG(LOG_ERR, "eapolclientitemid_set_password failed %d", 379 kret); 380 } 381 if (result != 0) { 382 EAPLOG(LOG_NOTICE, "eapolclientitemid_set_password() returned %d", 383 result); 384 } 385 my_CFRelease(&itemID_data); 386 return (result == 0); 387} 388 389STATIC Boolean 390authEAPOLClientItemIDRemovePasswordItem(EAPOLClientItemIDRef itemID) 391{ 392 AuthorizationExternalForm * auth_ext_p; 393 CFDataRef itemID_data; 394 kern_return_t kret; 395 int result = ENXIO; 396 mach_port_t server; 397 398 server = eapolcfg_auth_server_port(); 399 if (server == MACH_PORT_NULL) { 400 return (FALSE); 401 } 402 auth_ext_p = EAPOLClientItemIDGetAuthorizationExternalForm(itemID); 403 itemID_data = itemID_copy_data(itemID); 404 kret = eapolclientitemid_remove_password(server, 405 auth_ext_p->bytes, 406 sizeof(auth_ext_p->bytes), 407 (xmlData_t) 408 CFDataGetBytePtr(itemID_data), 409 CFDataGetLength(itemID_data), 410 &result); 411 if (kret != KERN_SUCCESS) { 412 EAPLOG(LOG_ERR, "eapolclientitemid_remove_password failed %d", 413 kret); 414 } 415 if (result != 0) { 416 EAPLOG(LOG_DEBUG, "eapolclientitemid_remove_password() returned %d", 417 result); 418 } 419 my_CFRelease(&itemID_data); 420 return (result == 0); 421} 422 423STATIC Boolean 424authEAPOLClientItemIDCopyPasswordItem(EAPOLClientItemIDRef itemID, 425 CFDataRef * name_data_p, 426 CFDataRef * password_data_p) 427{ 428 AuthorizationExternalForm * auth_ext_p; 429 CFDataRef itemID_data; 430 kern_return_t kret; 431 OOBDataOut_t name = NULL; 432 mach_msg_type_number_t name_length = 0; 433 boolean_t password_set = FALSE; 434 int result = ENXIO; 435 mach_port_t server; 436 437 server = eapolcfg_auth_server_port(); 438 if (server == MACH_PORT_NULL) { 439 return (FALSE); 440 } 441 auth_ext_p = EAPOLClientItemIDGetAuthorizationExternalForm(itemID); 442 itemID_data = itemID_copy_data(itemID); 443 kret = eapolclientitemid_check_password(server, 444 auth_ext_p->bytes, 445 sizeof(auth_ext_p->bytes), 446 (xmlData_t) 447 CFDataGetBytePtr(itemID_data), 448 CFDataGetLength(itemID_data), 449 &name, &name_length, 450 &password_set, 451 &result); 452 if (kret != KERN_SUCCESS) { 453 EAPLOG(LOG_ERR, "eapolclientitemid_check_password failed %d", 454 kret); 455 } 456 if (result != 0) { 457 EAPLOG(LOG_DEBUG, "eapolclientitemid_check_password() returned %d", 458 result); 459 } 460 461 if (name_data_p != NULL) { 462 if (name == NULL) { 463 *name_data_p = NULL; 464 } 465 else { 466 *name_data_p = CFDataCreate(NULL, (const UInt8 *)name, 467 name_length); 468 } 469 } 470 if (password_data_p != NULL) { 471 if (password_set == FALSE) { 472 *password_data_p = NULL; 473 } 474 else { 475 /* don't return the actual password, return a fake password */ 476#define FAKE_PASSWORD "XXXXXXXX" 477#define FAKE_PASSWORD_LENGTH (sizeof(FAKE_PASSWORD) - 1) 478 *password_data_p = CFDataCreate(NULL, 479 (const UInt8 *)FAKE_PASSWORD, 480 FAKE_PASSWORD_LENGTH); 481 } 482 } 483 if (name != NULL) { 484 (void)vm_deallocate(mach_task_self(), (vm_address_t)name, 485 name_length); 486 } 487 my_CFRelease(&itemID_data); 488 return (result == 0); 489} 490 491/** 492 ** EAPOLClientItemIDCopyUniqueString 493 ** - get the unique string for the itemID 494 **/ 495 496/* for password/name Item */ 497#define WLAN_SSID_STR "wlan.ssid" 498#define WLAN_DOMAIN_STR "wlan.domain" 499#define PROFILEID_STR "profileid" 500#define DEFAULT_STR "default" 501 502STATIC const char kItemDescription[] = "802.1X Password"; 503STATIC int kItemDescriptionLength = sizeof(kItemDescription) - 1; 504 505#define EAP_PREFIX_STR "com.apple.network.eap.%s.%s.%s" 506 507INLINE CFStringRef 508create_item_format(const char * domain, const char * type, const char * unique, 509 CFStringRef value) 510{ 511 CFStringRef str; 512 513 if (value != NULL) { 514 str = CFStringCreateWithFormat(NULL, NULL, 515 CFSTR(EAP_PREFIX_STR ".%@"), 516 domain, type, unique, value); 517 } 518 else { 519 str = CFStringCreateWithFormat(NULL, NULL, 520 CFSTR(EAP_PREFIX_STR), 521 domain, type, unique); 522 } 523 return (str); 524} 525 526STATIC CFStringRef 527EAPOLClientItemIDCopyUniqueString(EAPOLClientItemIDRef itemID, 528 EAPOLClientDomain domain, bool is_item) 529{ 530 const char * domain_str; 531 CFStringRef result = NULL; 532 CFStringRef profileID; 533 CFDataRef ssid; 534 CFStringRef ssid_str; 535 const char * type_str; 536 537 type_str = is_item ? "item" : "identity"; 538 domain_str = (domain == kEAPOLClientDomainSystem) ? "system" : "user"; 539 switch (itemID->type) { 540 case kEAPOLClientItemIDTypeWLANSSID: 541 ssid_str = my_CFStringCreateWithData(itemID->u.ssid); 542 result = create_item_format(domain_str, type_str, WLAN_SSID_STR, 543 ssid_str); 544 if (ssid_str != NULL) { 545 CFRelease(ssid_str); 546 } 547 break; 548 case kEAPOLClientItemIDTypeWLANDomain: 549 result = create_item_format(domain_str, type_str, 550 WLAN_DOMAIN_STR, itemID->u.domain); 551 break; 552 case kEAPOLClientItemIDTypeProfileID: 553 result = create_item_format(domain_str, type_str, PROFILEID_STR, 554 itemID->u.profileID); 555 break; 556 case kEAPOLClientItemIDTypeProfile: 557 ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(itemID->u.profile, 558 NULL); 559 if (ssid != NULL) { 560 ssid_str = my_CFStringCreateWithData(ssid); 561 result = create_item_format(domain_str, type_str, WLAN_SSID_STR, 562 ssid_str); 563 if (ssid_str != NULL) { 564 CFRelease(ssid_str); 565 } 566 } 567 else { 568 CFStringRef wlan_domain; 569 570 wlan_domain = EAPOLClientProfileGetWLANDomain(itemID->u.profile); 571 if (wlan_domain != NULL) { 572 result = create_item_format(domain_str, type_str, 573 WLAN_DOMAIN_STR, wlan_domain); 574 } 575 else { 576 profileID = EAPOLClientProfileGetID(itemID->u.profile); 577 result = create_item_format(domain_str, type_str, PROFILEID_STR, 578 profileID); 579 } 580 } 581 break; 582 case kEAPOLClientItemIDTypeDefault: 583 result = create_item_format(domain_str, type_str, DEFAULT_STR, NULL); 584 break; 585 default: 586 break; 587 } 588 return (result); 589} 590 591/** 592 ** CF object glue code 593 **/ 594STATIC CFStringRef __EAPOLClientItemIDCopyDebugDesc(CFTypeRef cf); 595STATIC void __EAPOLClientItemIDDeallocate(CFTypeRef cf); 596STATIC Boolean __EAPOLClientItemIDEqual(CFTypeRef cf1, CFTypeRef cf2); 597STATIC CFHashCode __EAPOLClientItemIDHash(CFTypeRef cf); 598 599STATIC CFTypeID __kEAPOLClientItemIDTypeID = _kCFRuntimeNotATypeID; 600 601STATIC const CFRuntimeClass __EAPOLClientItemIDClass = { 602 0, /* version */ 603 "EAPOLClientItemID", /* className */ 604 NULL, /* init */ 605 NULL, /* copy */ 606 __EAPOLClientItemIDDeallocate, /* deallocate */ 607 __EAPOLClientItemIDEqual, /* equal */ 608 __EAPOLClientItemIDHash, /* hash */ 609 NULL, /* copyFormattingDesc */ 610 __EAPOLClientItemIDCopyDebugDesc /* copyDebugDesc */ 611}; 612 613STATIC CFStringRef 614__EAPOLClientItemIDCopyDebugDesc(CFTypeRef cf) 615{ 616 CFAllocatorRef allocator = CFGetAllocator(cf); 617 EAPOLClientItemIDRef itemID = (EAPOLClientItemIDRef)cf; 618 CFStringRef profileID; 619 CFMutableStringRef result; 620 CFStringRef ssid_str; 621 622 result = CFStringCreateMutable(allocator, 0); 623 CFStringAppendFormat(result, NULL, 624 CFSTR("<EAPOLClientItemID %p [%p]> {"), cf, allocator); 625 switch (itemID->type) { 626 case kEAPOLClientItemIDTypeWLANSSID: 627 ssid_str = my_CFStringCreateWithData(itemID->u.ssid); 628 CFStringAppendFormat(result, NULL, CFSTR("WLAN SSID = %@"), 629 ssid_str); 630 CFRelease(ssid_str); 631 break; 632 case kEAPOLClientItemIDTypeWLANDomain: 633 CFStringAppendFormat(result, NULL, CFSTR("WLAN domain = %@"), 634 itemID->u.domain); 635 break; 636 case kEAPOLClientItemIDTypeProfileID: 637 CFStringAppendFormat(result, NULL, CFSTR("ProfileID = %@"), 638 itemID->u.profileID); 639 break; 640 case kEAPOLClientItemIDTypeProfile: 641 profileID = EAPOLClientProfileGetID(itemID->u.profile); 642 CFStringAppendFormat(result, NULL, CFSTR("Profile = %@"), 643 profileID); 644 break; 645 case kEAPOLClientItemIDTypeDefault: 646 CFStringAppend(result, CFSTR("Default")); 647 break; 648 default: 649 break; 650 } 651 CFStringAppend(result, CFSTR("}")); 652 return result; 653} 654 655 656STATIC void 657__EAPOLClientItemIDDeallocate(CFTypeRef cf) 658{ 659 EAPOLClientItemIDRef itemID = (EAPOLClientItemIDRef)cf; 660 661 switch (itemID->type) { 662 case kEAPOLClientItemIDTypeWLANSSID: 663 CFRelease(itemID->u.ssid); 664 break; 665 case kEAPOLClientItemIDTypeWLANDomain: 666 CFRelease(itemID->u.domain); 667 break; 668 case kEAPOLClientItemIDTypeProfileID: 669 CFRelease(itemID->u.profileID); 670 break; 671 case kEAPOLClientItemIDTypeProfile: 672 CFRelease(itemID->u.profile); 673 break; 674 default: 675 break; 676 } 677 return; 678} 679 680 681STATIC Boolean 682__EAPOLClientItemIDEqual(CFTypeRef cf1, CFTypeRef cf2) 683{ 684 EAPOLClientItemIDRef id1 = (EAPOLClientItemIDRef)cf1; 685 EAPOLClientItemIDRef id2 = (EAPOLClientItemIDRef)cf2; 686 687 if (id1->type != id2->type) { 688 return (FALSE); 689 } 690 return (CFEqual(id1->u.ptr, id2->u.ptr)); 691} 692 693STATIC CFHashCode 694__EAPOLClientItemIDHash(CFTypeRef cf) 695{ 696 EAPOLClientItemIDRef itemID = (EAPOLClientItemIDRef)cf; 697 698 return (CFHash(itemID->u.ptr)); 699} 700 701 702STATIC void 703__EAPOLClientItemIDInitialize(void) 704{ 705 /* initialize runtime */ 706 __kEAPOLClientItemIDTypeID 707 = _CFRuntimeRegisterClass(&__EAPOLClientItemIDClass); 708 return; 709} 710 711STATIC void 712__EAPOLClientItemIDRegisterClass(void) 713{ 714 STATIC pthread_once_t initialized = PTHREAD_ONCE_INIT; 715 716 pthread_once(&initialized, __EAPOLClientItemIDInitialize); 717 return; 718} 719 720 721STATIC EAPOLClientItemIDRef 722__EAPOLClientItemIDAllocate(CFAllocatorRef allocator) 723{ 724 EAPOLClientItemIDRef itemID; 725 726 __EAPOLClientItemIDRegisterClass(); 727 728 itemID = (EAPOLClientItemIDRef) 729 _CFRuntimeCreateInstance(allocator, 730 __kEAPOLClientItemIDTypeID, 731 sizeof(*itemID) - sizeof(CFRuntimeBase), 732 NULL); 733 return (itemID); 734} 735 736/** 737 ** EAPOLClientItemID APIs 738 **/ 739 740CFTypeID 741EAPOLClientItemIDGetTypeID(void) 742{ 743 __EAPOLClientItemIDRegisterClass(); 744 return (__kEAPOLClientItemIDTypeID); 745} 746 747/* 748 * Function: EAPOLClientItemIDCreateWithProfileID 749 * 750 * Purpose: 751 * Create an EAPOLClientItemID instance based on the supplied profileID 752 */ 753EAPOLClientItemIDRef 754EAPOLClientItemIDCreateWithProfileID(CFStringRef profileID) 755{ 756 EAPOLClientItemIDRef itemID; 757 758 itemID = __EAPOLClientItemIDAllocate(CFGetAllocator(profileID)); 759 if (itemID == NULL) { 760 return (NULL); 761 } 762 itemID->type = kEAPOLClientItemIDTypeProfileID; 763 itemID->u.profileID = CFRetain(profileID); 764 return (itemID); 765} 766 767/* 768 * Function: EAPOLClientItemIDCreateWithWLANSSID 769 * 770 * Purpose: 771 * Create an EAPOLClientItemID instance based on the supplied WLAN SSID. 772 */ 773EAPOLClientItemIDRef 774EAPOLClientItemIDCreateWithWLANSSID(CFDataRef ssid) 775{ 776 EAPOLClientItemIDRef itemID; 777 778 itemID = __EAPOLClientItemIDAllocate(CFGetAllocator(ssid)); 779 if (itemID == NULL) { 780 return (NULL); 781 } 782 itemID->type = kEAPOLClientItemIDTypeWLANSSID; 783 itemID->u.ssid = CFRetain(ssid); 784 return (itemID); 785} 786 787/* 788 * Function: EAPOLClientItemIDCreateWithWLANDomain 789 * 790 * Purpose: 791 * Create an EAPOLClientItemID instance based on the supplied WLAN 792 * Hotspot 2.0 domain name. 793 */ 794EAPOLClientItemIDRef 795EAPOLClientItemIDCreateWithWLANDomain(CFStringRef domain) 796{ 797 EAPOLClientItemIDRef itemID; 798 799 itemID = __EAPOLClientItemIDAllocate(CFGetAllocator(domain)); 800 if (itemID == NULL) { 801 return (NULL); 802 } 803 itemID->type = kEAPOLClientItemIDTypeWLANDomain; 804 itemID->u.domain = CFRetain(domain); 805 return (itemID); 806} 807 808/* 809 * Function: EAPOLClientItemIDCreateWithProfile 810 * 811 * Purpose: 812 * Create an EAPOLClientItemID instance based on the supplied 813 * EAPOLClientProfileRef. 814 */ 815EAPOLClientItemIDRef 816EAPOLClientItemIDCreateWithProfile(EAPOLClientProfileRef profile) 817{ 818 EAPOLClientItemIDRef itemID; 819 820 itemID = __EAPOLClientItemIDAllocate(CFGetAllocator(profile)); 821 if (itemID == NULL) { 822 return (NULL); 823 } 824 itemID->type = kEAPOLClientItemIDTypeProfile; 825 CFRetain(profile); 826 itemID->u.profile = profile; 827 return (itemID); 828} 829 830/* 831 * Function: EAPOLClientItemIDCreateDefault 832 * 833 * Purpose: 834 * Create an EAPOLClientItemID instance that indicates that the default 835 * authentication parameters and default keychain items are to be used. 836 */ 837EAPOLClientItemIDRef 838EAPOLClientItemIDCreateDefault(void) 839{ 840 EAPOLClientItemIDRef itemID; 841 842 itemID = __EAPOLClientItemIDAllocate(NULL); 843 if (itemID == NULL) { 844 return (NULL); 845 } 846 itemID->type = kEAPOLClientItemIDTypeDefault; 847 return (itemID); 848} 849 850/* 851 * Function: EAPOLClientItemIDCopyPasswordItem 852 * 853 * Purpose: 854 * Retrieve the password item from secure storage for the particular itemID 855 * in the specified domain. 856 * 857 * Returns: 858 * FALSE if no such item exists, and both *username_p and *password_p 859 * are set to NULL. 860 * 861 * TRUE if an item exists, and either of both *username_p and *password_p 862 * are set to a non-NULL value. 863 */ 864Boolean 865EAPOLClientItemIDCopyPasswordItem(EAPOLClientItemIDRef itemID, 866 EAPOLClientDomain domain, 867 CFDataRef * username_p, 868 CFDataRef * password_p) 869{ 870 CFDictionaryRef attrs = NULL; 871 int count; 872 SecKeychainRef keychain = NULL; 873 const void * keys[2]; 874 CFArrayRef req_props = NULL; 875 OSStatus status = errSecParam; 876 CFStringRef unique_string; 877 878 count = 0; 879 if (username_p == NULL && password_p == NULL) { 880 return (FALSE); 881 } 882 switch (domain) { 883 case kEAPOLClientDomainUser: 884 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainUser, 885 &keychain); 886 if (status != noErr) { 887 fprintf(stderr, "EAPOLClientItemIDCopyPasswordItem can't get" 888 " User keychain\n"); 889 return (FALSE); 890 } 891 break; 892 case kEAPOLClientDomainSystem: 893 if (EAPOLClientItemIDGetAuthorizationExternalForm(itemID) != NULL) { 894 return (authEAPOLClientItemIDCopyPasswordItem(itemID, username_p, 895 password_p)); 896 } 897 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, 898 &keychain); 899 if (status != noErr) { 900 fprintf(stderr, "EAPOLClientItemIDCopyPasswordItem can't get" 901 " System keychain\n"); 902 return (FALSE); 903 } 904 break; 905 default: 906 return (FALSE); 907 } 908 if (username_p != NULL) { 909 keys[count] = kEAPSecKeychainPropAccount; 910 count++; 911 *username_p = NULL; 912 } 913 if (password_p != NULL) { 914 keys[count] = kEAPSecKeychainPropPassword; 915 count++; 916 *password_p = NULL; 917 } 918 req_props = CFArrayCreate(NULL, keys, count, 919 &kCFTypeArrayCallBacks); 920 unique_string = EAPOLClientItemIDCopyUniqueString(itemID, domain, TRUE); 921 status = EAPSecKeychainPasswordItemCopy2(keychain, 922 unique_string, 923 req_props, 924 &attrs); 925 if (status != noErr) { 926 goto done; 927 } 928 if (username_p != NULL) { 929 *username_p 930 = my_CFDictionaryCopyValue(attrs, kEAPSecKeychainPropAccount); 931 } 932 if (password_p != NULL) { 933 *password_p 934 = my_CFDictionaryCopyValue(attrs, kEAPSecKeychainPropPassword); 935 936 } 937 938 done: 939 my_CFRelease(&unique_string); 940 my_CFRelease(&req_props); 941 my_CFRelease(&attrs); 942 my_CFRelease(&keychain); 943 return (status == noErr); 944} 945 946/* 947 * Function: EAPOLClientItemIDSetPasswordItem 948 * 949 * Purpose: 950 * Set the password item in secure storage for the specified itemID 951 * in the specified domain. 952 * 953 * Passing an empty 'username' or 'password' removes the corresponding 954 * attribute. If both 'username' and 'password' are empty, the item is 955 * also removed. An empty value is a non-NULL CFDataRef of length 0. 956 * 957 * Passing NULL for 'username' or 'password' means that the corresponding 958 * item attribute is left alone. If both 'username" and 'password' are 959 * NULL, the call has no effect, but TRUE is still returned. 960 * 961 * Passing non-NULL, non-empty 'username' or 'password' sets the 962 * corresponding item attribute to the specified value. If the item 963 * does not exist, it will be created. 964 * 965 * Returns: 966 * FALSE if the operation did not succeed, TRUE otherwise. 967 */ 968Boolean 969EAPOLClientItemIDSetPasswordItem(EAPOLClientItemIDRef itemID, 970 EAPOLClientDomain domain, 971 CFDataRef name, CFDataRef password) 972{ 973 CFMutableDictionaryRef attrs = NULL; 974 CFDataRef data; 975 SecKeychainRef keychain = NULL; 976 CFDataRef ssid; 977 OSStatus status = errSecParam; 978 CFStringRef unique_string; 979 980 if (name == NULL && password == NULL) { 981 return (TRUE); 982 } 983 switch (domain) { 984 case kEAPOLClientDomainUser: 985 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainUser, 986 &keychain); 987 if (status != noErr) { 988 fprintf(stderr, "EAPOLClientItemIDSetPasswordItem can't get" 989 " User keychain, %s (%d)\n", 990 EAPSecurityErrorString(status), (int)status); 991 return (FALSE); 992 } 993 break; 994 case kEAPOLClientDomainSystem: 995 if (EAPOLClientItemIDGetAuthorizationExternalForm(itemID) != NULL) { 996 return (authEAPOLClientItemIDSetPasswordItem(itemID, name, 997 password)); 998 } 999 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, 1000 &keychain); 1001 if (status != noErr) { 1002 fprintf(stderr, "EAPOLClientItemIDSetPasswordItem can't get" 1003 " System keychain, %s (%d)\n", 1004 EAPSecurityErrorString(status), (int)status); 1005 return (FALSE); 1006 } 1007 break; 1008 default: 1009 return (FALSE); 1010 } 1011 1012 /* populate an attributes dictionary */ 1013 attrs = CFDictionaryCreateMutable(NULL, 0, 1014 &kCFTypeDictionaryKeyCallBacks, 1015 &kCFTypeDictionaryValueCallBacks); 1016 1017 /* Description */ 1018 data = CFDataCreate(NULL, (UInt8 *)kItemDescription, 1019 kItemDescriptionLength); 1020 CFDictionarySetValue(attrs, kEAPSecKeychainPropDescription, data); 1021 CFRelease(data); 1022 1023 /* Label */ 1024 switch (itemID->type) { 1025 case kEAPOLClientItemIDTypeWLANSSID: 1026 CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, 1027 itemID->u.ssid); 1028 break; 1029 case kEAPOLClientItemIDTypeWLANDomain: { 1030 CFDataRef label_data; 1031 1032 label_data = my_CFDataCreateWithString(itemID->u.domain); 1033 CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, 1034 label_data); 1035 CFRelease(label_data); 1036 break; 1037 } 1038 case kEAPOLClientItemIDTypeProfileID: { 1039 CFDataRef label_data; 1040 1041 label_data = my_CFDataCreateWithString(itemID->u.profileID); 1042 CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, label_data); 1043 CFRelease(label_data); 1044 break; 1045 } 1046 case kEAPOLClientItemIDTypeProfile: 1047 ssid = EAPOLClientProfileGetWLANSSIDAndSecurityType(itemID->u.profile, 1048 NULL); 1049 if (ssid != NULL) { 1050 CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, 1051 ssid); 1052 } 1053 else { 1054 CFStringRef label; 1055 CFDataRef label_data; 1056 1057 label = EAPOLClientProfileGetUserDefinedName(itemID->u.profile); 1058 if (label == NULL) { 1059 label = EAPOLClientProfileGetWLANDomain(itemID->u.profile); 1060 if (label == NULL) { 1061 label = EAPOLClientProfileGetID(itemID->u.profile); 1062 } 1063 } 1064 label_data = my_CFDataCreateWithString(label); 1065 CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, label_data); 1066 CFRelease(label_data); 1067 } 1068 break; 1069 case kEAPOLClientItemIDTypeDefault: { 1070 CFDataRef label_data; 1071 1072 /* XXX localize? */ 1073 label_data = my_CFDataCreateWithString(CFSTR("Default")); 1074 CFDictionarySetValue(attrs, kEAPSecKeychainPropLabel, label_data); 1075 CFRelease(label_data); 1076 break; 1077 } 1078 default: 1079 goto done; 1080 } 1081 1082 /* Account */ 1083 if (name != NULL) { 1084 CFDictionarySetValue(attrs, kEAPSecKeychainPropAccount, name); 1085 } 1086 1087 /* Password */ 1088 if (password != NULL) { 1089 CFDictionarySetValue(attrs, kEAPSecKeychainPropPassword, password); 1090 }; 1091 1092 if (domain == kEAPOLClientDomainUser) { 1093 CFArrayRef trusted_apps; 1094 1095 /* Trusted Applications */ 1096 trusted_apps = copy_trusted_applications(FALSE); 1097 if (trusted_apps != NULL) { 1098 CFDictionarySetValue(attrs, 1099 kEAPSecKeychainPropTrustedApplications, 1100 trusted_apps); 1101 CFRelease(trusted_apps); 1102 } 1103 } 1104 else { 1105 CFDictionarySetValue(attrs, 1106 kEAPSecKeychainPropAllowRootAccess, 1107 kCFBooleanTrue); 1108 } 1109 unique_string = EAPOLClientItemIDCopyUniqueString(itemID, domain, TRUE); 1110 status = EAPSecKeychainPasswordItemSet2(keychain, unique_string, 1111 attrs); 1112 if (status == errSecItemNotFound) { 1113 status = EAPSecKeychainPasswordItemCreate(keychain, 1114 unique_string, 1115 attrs); 1116 } 1117 my_CFRelease(&unique_string); 1118 if (status != noErr) { 1119 EAPLOG(LOG_NOTICE, 1120 "EAPOLClientItemID: failed to set keychain item, %d", 1121 (int)status); 1122 } 1123 1124 done: 1125 my_CFRelease(&attrs); 1126 my_CFRelease(&keychain); 1127 return (status == noErr); 1128} 1129 1130/* 1131 * Function: EAPOLClientItemIDRemovePasswordItem 1132 * 1133 * Purpose: 1134 * Remove the password item in secure storage for the specified itemID 1135 * in the specified domain. 1136 * 1137 * Returns: 1138 * FALSE if the operation did not succeed, TRUE otherwise. 1139 */ 1140Boolean 1141EAPOLClientItemIDRemovePasswordItem(EAPOLClientItemIDRef itemID, 1142 EAPOLClientDomain domain) 1143{ 1144 SecKeychainRef keychain = NULL; 1145 OSStatus status = errSecParam; 1146 CFStringRef unique_string; 1147 1148 switch (domain) { 1149 case kEAPOLClientDomainUser: 1150 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainUser, 1151 &keychain); 1152 if (status != noErr) { 1153 fprintf(stderr, "EAPOLClientItemIDSetPasswordItem can't get" 1154 " User keychain, %s (%d)\n", 1155 EAPSecurityErrorString(status), (int)status); 1156 return (FALSE); 1157 } 1158 break; 1159 case kEAPOLClientDomainSystem: 1160 if (EAPOLClientItemIDGetAuthorizationExternalForm(itemID) != NULL) { 1161 return (authEAPOLClientItemIDRemovePasswordItem(itemID)); 1162 } 1163 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, 1164 &keychain); 1165 if (status != noErr) { 1166 fprintf(stderr, "EAPOLClientItemIDSetPasswordItem can't get" 1167 " System keychain, %s (%d)\n", 1168 EAPSecurityErrorString(status), (int)status); 1169 return (FALSE); 1170 } 1171 break; 1172 default: 1173 return (FALSE); 1174 } 1175 unique_string = EAPOLClientItemIDCopyUniqueString(itemID, domain, TRUE); 1176 status = EAPSecKeychainPasswordItemRemove(keychain, 1177 unique_string); 1178 my_CFRelease(&unique_string); 1179 my_CFRelease(&keychain); 1180 return (status == noErr); 1181} 1182 1183/* 1184 * Function: EAPOLClientItemIDCopyIdentity 1185 * 1186 * Purpose: 1187 * Retrieve the identity associated with the particular itemID 1188 * in the specified domain. 1189 * 1190 * Returns: 1191 * non-NULL SecIdentityRef when match can be found for the item ID, 1192 * NULL otherwise. 1193 */ 1194SecIdentityRef 1195EAPOLClientItemIDCopyIdentity(EAPOLClientItemIDRef itemID, 1196 EAPOLClientDomain domain) 1197{ 1198 SecPreferencesDomain current_domain; 1199 SecIdentityRef identity = NULL; 1200 SecPreferencesDomain required_domain; 1201 OSStatus status; 1202 CFStringRef unique_string; 1203 1204 switch (domain) { 1205 case kEAPOLClientDomainUser: 1206 required_domain = kSecPreferencesDomainUser; 1207 break; 1208 case kEAPOLClientDomainSystem: 1209 required_domain = kSecPreferencesDomainSystem; 1210 break; 1211 default: 1212 return (NULL); 1213 } 1214 status = SecKeychainGetPreferenceDomain(¤t_domain); 1215 if (status != noErr) { 1216 return (NULL); 1217 } 1218 if (current_domain != required_domain) { 1219 status = SecKeychainSetPreferenceDomain(required_domain); 1220 if (status != noErr) { 1221 return (NULL); 1222 } 1223 } 1224 unique_string = EAPOLClientItemIDCopyUniqueString(itemID, domain, FALSE); 1225 identity = SecIdentityCopyPreferred(unique_string, NULL, NULL); 1226 if (current_domain != required_domain) { 1227 (void)SecKeychainSetPreferenceDomain(current_domain); 1228 } 1229 my_CFRelease(&unique_string); 1230 return (identity); 1231} 1232 1233/* 1234 * Function: EAPOLClientItemIDSetIdentity 1235 * 1236 * Purpose: 1237 * Associate an identity with the specified itemID in the specified 1238 * domain. 1239 * 1240 * If the identity is NULL, the identity preference is removed. 1241 * 1242 * Returns: 1243 * FALSE if the operation did not succeed, TRUE otherwise. 1244 */ 1245Boolean 1246EAPOLClientItemIDSetIdentity(EAPOLClientItemIDRef itemID, 1247 EAPOLClientDomain domain, 1248 SecIdentityRef identity) 1249{ 1250 SecPreferencesDomain current_domain; 1251 SecPreferencesDomain required_domain; 1252 OSStatus status; 1253 CFStringRef unique_string; 1254 1255 switch (domain) { 1256 case kEAPOLClientDomainUser: 1257 required_domain = kSecPreferencesDomainUser; 1258 break; 1259 case kEAPOLClientDomainSystem: 1260 if (EAPOLClientItemIDGetAuthorizationExternalForm(itemID) != NULL) { 1261 return (authEAPOLClientItemIDSetIdentity(itemID, identity)); 1262 } 1263 required_domain = kSecPreferencesDomainSystem; 1264 break; 1265 default: 1266 return (FALSE); 1267 } 1268 1269 status = SecKeychainGetPreferenceDomain(¤t_domain); 1270 if (status != noErr) { 1271 return (FALSE); 1272 } 1273 if (required_domain != current_domain) { 1274 status = SecKeychainSetPreferenceDomain(required_domain); 1275 if (status != noErr) { 1276 return (FALSE); 1277 } 1278 } 1279 unique_string = EAPOLClientItemIDCopyUniqueString(itemID, domain, FALSE); 1280 status = SecIdentitySetPreferred(identity, unique_string, NULL); 1281 if (status != noErr) { 1282 fprintf(stderr, "SecIdentitySetPreference failed %s (%d)\n", 1283 EAPSecurityErrorString(status), (int)status); 1284 } 1285 1286 if (current_domain != required_domain) { 1287 (void)SecKeychainSetPreferenceDomain(current_domain); 1288 } 1289 my_CFRelease(&unique_string); 1290 return (status == noErr); 1291} 1292 1293/** 1294 ** Private functions 1295 **/ 1296 1297 1298CFStringRef 1299EAPOLClientItemIDGetProfileID(EAPOLClientItemIDRef itemID) 1300{ 1301 switch (itemID->type) { 1302 case kEAPOLClientItemIDTypeProfileID: 1303 return (itemID->u.profileID); 1304 case kEAPOLClientItemIDTypeProfile: 1305 return (EAPOLClientProfileGetID(itemID->u.profile)); 1306 default: 1307 break; 1308 } 1309 return (NULL); 1310} 1311 1312CFDataRef 1313EAPOLClientItemIDGetWLANSSID(EAPOLClientItemIDRef itemID) 1314{ 1315 switch (itemID->type) { 1316 case kEAPOLClientItemIDTypeWLANSSID: 1317 return (itemID->u.ssid); 1318 case kEAPOLClientItemIDTypeProfile: 1319 return (EAPOLClientProfileGetWLANSSIDAndSecurityType(itemID->u.profile, 1320 NULL)); 1321 default: 1322 break; 1323 } 1324 return (NULL); 1325} 1326 1327CFStringRef 1328EAPOLClientItemIDGetWLANDomain(EAPOLClientItemIDRef itemID) 1329{ 1330 switch (itemID->type) { 1331 case kEAPOLClientItemIDTypeWLANDomain: 1332 return (itemID->u.domain); 1333 case kEAPOLClientItemIDTypeProfile: 1334 return (EAPOLClientProfileGetWLANDomain(itemID->u.profile)); 1335 default: 1336 break; 1337 } 1338 return (NULL); 1339} 1340 1341EAPOLClientProfileRef 1342EAPOLClientItemIDGetProfile(EAPOLClientItemIDRef itemID) 1343{ 1344 switch (itemID->type) { 1345 case kEAPOLClientItemIDTypeProfile: 1346 return (itemID->u.profile); 1347 default: 1348 break; 1349 } 1350 return (NULL); 1351} 1352 1353#define kItemProfileID CFSTR("ProfileID") 1354#define kItemDomain CFSTR("Domain") 1355#define kItemSSID CFSTR("SSID") 1356#define kItemDefault CFSTR("Default") 1357 1358CFDictionaryRef 1359EAPOLClientItemIDCopyDictionary(EAPOLClientItemIDRef itemID) 1360{ 1361 const void * key; 1362 CFStringRef profileID; 1363 const void * value; 1364 1365 profileID = EAPOLClientItemIDGetProfileID(itemID); 1366 if (profileID != NULL) { 1367 key = (const void *)kItemProfileID; 1368 value = (const void *)profileID; 1369 } 1370 else { 1371 CFDataRef ssid = EAPOLClientItemIDGetWLANSSID(itemID); 1372 1373 if (ssid != NULL) { 1374 key = (const void *)kItemSSID; 1375 value = (const void *)ssid; 1376 } 1377 else { 1378 switch (itemID->type) { 1379 case kEAPOLClientItemIDTypeWLANDomain: 1380 key = (const void *)kItemDomain; 1381 value = (const void *)itemID->u.domain; 1382 break; 1383 case kEAPOLClientItemIDTypeDefault: 1384 key = (const void *)kItemDefault; 1385 value = (const void *)kCFBooleanTrue; 1386 break; 1387 default: 1388 return (NULL); 1389 } 1390 } 1391 } 1392 return (CFDictionaryCreate(NULL, &key, &value, 1, 1393 &kCFTypeDictionaryKeyCallBacks, 1394 &kCFTypeDictionaryValueCallBacks)); 1395} 1396 1397EAPOLClientItemIDRef 1398EAPOLClientItemIDCreateWithDictionary(EAPOLClientConfigurationRef cfg, 1399 CFDictionaryRef dict) 1400{ 1401 CFStringRef domain; 1402 EAPOLClientProfileRef profile; 1403 CFStringRef profileID; 1404 CFDataRef ssid; 1405 1406 if (isA_CFDictionary(dict) == NULL) { 1407 return (NULL); 1408 } 1409 profileID = CFDictionaryGetValue(dict, kItemProfileID); 1410 if (isA_CFString(profileID) != NULL) { 1411 if (cfg != NULL) { 1412 profile = EAPOLClientConfigurationGetProfileWithID(cfg, profileID); 1413 if (profile != NULL) { 1414 return (EAPOLClientItemIDCreateWithProfile(profile)); 1415 } 1416 } 1417 return (EAPOLClientItemIDCreateWithProfileID(profileID)); 1418 } 1419 ssid = CFDictionaryGetValue(dict, kItemSSID); 1420 if (isA_CFData(ssid) != NULL) { 1421 if (cfg != NULL) { 1422 profile = EAPOLClientConfigurationGetProfileWithWLANSSID(cfg, ssid); 1423 if (profile != NULL) { 1424 return (EAPOLClientItemIDCreateWithProfile(profile)); 1425 } 1426 } 1427 return (EAPOLClientItemIDCreateWithWLANSSID(ssid)); 1428 } 1429 domain = CFDictionaryGetValue(dict, kItemDomain); 1430 if (isA_CFString(domain) != NULL) { 1431 if (cfg != NULL) { 1432 profile 1433 = EAPOLClientConfigurationGetProfileWithWLANDomain(cfg, 1434 domain); 1435 if (profile != NULL) { 1436 return (EAPOLClientItemIDCreateWithProfile(profile)); 1437 } 1438 } 1439 return (EAPOLClientItemIDCreateWithWLANDomain(domain)); 1440 } 1441 if (CFDictionaryGetValue(dict, kItemDefault) != NULL) { 1442 return (EAPOLClientItemIDCreateDefault()); 1443 } 1444 return (NULL); 1445} 1446 1447PRIVATE_EXTERN AuthorizationExternalForm * 1448EAPOLClientItemIDGetAuthorizationExternalForm(EAPOLClientItemIDRef itemID) 1449{ 1450 EAPOLClientConfigurationRef cfg; 1451 EAPOLClientProfileRef profile; 1452 1453 profile = EAPOLClientItemIDGetProfile(itemID); 1454 if (profile == NULL) { 1455 return (NULL); 1456 } 1457 cfg = EAPOLClientProfileGetConfiguration(profile); 1458 if (cfg == NULL) { 1459 return (NULL); 1460 } 1461 return (EAPOLClientConfigurationGetAuthorizationExternalForm(cfg)); 1462} 1463