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