this repo has no description
at fixPythonPipStalling 2236 lines 58 kB view raw
1/* 2 * Copyright (c) 2006-2012, 2015-2018 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#include <CoreFoundation/CoreFoundation.h> 25#include <CoreFoundation/CFRuntime.h> 26#include "SCNetworkConfigurationInternal.h" 27#include <notify.h> 28#include <pthread.h> 29 30 31#pragma mark - 32#pragma mark SCUserPreferences 33 34 35typedef struct { 36 37 // base CFType information 38 CFRuntimeBase cfBase; 39 40 // serviceID 41 CFStringRef serviceID; 42 43 // user preferences [unique] id 44 CFStringRef prefsID; 45 46} SCUserPreferencesPrivate, *SCUserPreferencesPrivateRef; 47 48 49static CFStringRef __SCUserPreferencesCopyDescription (CFTypeRef cf); 50static void __SCUserPreferencesDeallocate (CFTypeRef cf); 51static Boolean __SCUserPreferencesEqual (CFTypeRef cf1, CFTypeRef cf2); 52static CFHashCode __SCUserPreferencesHash (CFTypeRef cf); 53 54 55static CFTypeID __kSCUserPreferencesTypeID = _kCFRuntimeNotATypeID; 56 57 58static const CFRuntimeClass __SCUserPreferencesClass = { 59 0, // version 60 "SCUserPreferences", // className 61 NULL, // init 62 NULL, // copy 63 __SCUserPreferencesDeallocate, // dealloc 64 __SCUserPreferencesEqual, // equal 65 __SCUserPreferencesHash, // hash 66 NULL, // copyFormattingDesc 67 __SCUserPreferencesCopyDescription // copyDebugDesc 68}; 69 70 71static pthread_once_t initialized = PTHREAD_ONCE_INIT; 72 73 74static CFStringRef 75__SCUserPreferencesCopyDescription(CFTypeRef cf) 76{ 77 CFAllocatorRef allocator = CFGetAllocator(cf); 78 CFMutableStringRef result; 79 SCUserPreferencesPrivateRef prefsPrivate = (SCUserPreferencesPrivateRef)cf; 80 81 result = CFStringCreateMutable(allocator, 0); 82 CFStringAppendFormat(result, NULL, CFSTR("<SCUserPreferences %p [%p]> {"), cf, allocator); 83 CFStringAppendFormat(result, NULL, CFSTR("service = %@"), prefsPrivate->serviceID); 84 CFStringAppendFormat(result, NULL, CFSTR(", id = %@"), prefsPrivate->prefsID); 85 CFStringAppendFormat(result, NULL, CFSTR("}")); 86 87 return result; 88} 89 90 91static void 92__SCUserPreferencesDeallocate(CFTypeRef cf) 93{ 94 SCUserPreferencesPrivateRef prefsPrivate = (SCUserPreferencesPrivateRef)cf; 95 96 /* release resources */ 97 98 CFRelease(prefsPrivate->prefsID); 99 CFRelease(prefsPrivate->serviceID); 100 101 return; 102} 103 104 105static Boolean 106__SCUserPreferencesEqual(CFTypeRef cf1, CFTypeRef cf2) 107{ 108 SCUserPreferencesPrivateRef s1 = (SCUserPreferencesPrivateRef)cf1; 109 SCUserPreferencesPrivateRef s2 = (SCUserPreferencesPrivateRef)cf2; 110 111 if (s1 == s2) 112 return TRUE; 113 114 if (!CFEqual(s1->prefsID, s2->prefsID)) 115 return FALSE; // if not the same [unique] prefs identifier 116 117 return TRUE; 118} 119 120 121static CFHashCode 122__SCUserPreferencesHash(CFTypeRef cf) 123{ 124 SCUserPreferencesPrivateRef prefsPrivate = (SCUserPreferencesPrivateRef)cf; 125 126 return CFHash(prefsPrivate->prefsID); 127} 128 129 130static void 131__SCUserPreferencesInitialize(void) 132{ 133 __kSCUserPreferencesTypeID = _CFRuntimeRegisterClass(&__SCUserPreferencesClass); 134 return; 135} 136 137 138static SCUserPreferencesPrivateRef 139__SCUserPreferencesCreatePrivate(CFAllocatorRef allocator, 140 CFStringRef serviceID, 141 CFStringRef prefsID) 142{ 143 SCUserPreferencesPrivateRef prefsPrivate; 144 uint32_t size; 145 146 /* initialize runtime */ 147 pthread_once(&initialized, __SCUserPreferencesInitialize); 148 149 /* allocate target */ 150 size = sizeof(SCUserPreferencesPrivate) - sizeof(CFRuntimeBase); 151 prefsPrivate = (SCUserPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator, 152 __kSCUserPreferencesTypeID, 153 size, 154 NULL); 155 if (prefsPrivate == NULL) { 156 return NULL; 157 } 158 159 /* initialize non-zero/NULL members */ 160 prefsPrivate->serviceID = CFStringCreateCopy(NULL, serviceID); 161 prefsPrivate->prefsID = CFStringCreateCopy(NULL, prefsID); 162 163 return prefsPrivate; 164} 165 166 167static __inline__ CFTypeRef 168isA_SCUserPreferences(CFTypeRef obj) 169{ 170 return (isA_CFType(obj, SCUserPreferencesGetTypeID())); 171} 172 173 174#pragma mark - 175#pragma mark SCUserPreferences SPIs 176 177 178#define USER_PREFERENCES_NOTIFICATION "com.apple.networkConnect" 179#define USER_PREFERENCES_APPLICATION_ID CFSTR("com.apple.networkConnect") 180#define USER_PREFERENCES_ID CFSTR("UniqueIdentifier") 181#define USER_PREFERENCES_DEFAULT CFSTR("ConnectByDefault") 182 183 184#define LOG_CFPREFERENCES_CHANGES 185#ifdef LOG_CFPREFERENCES_CHANGES 186#include <fcntl.h> 187#include <unistd.h> 188#include <sys/stat.h> 189#include <sys/time.h> 190static void 191logCFPreferencesChange(CFStringRef serviceID, CFArrayRef newPreferences) 192{ 193 CFBooleanRef bVal; 194 char dir[256]; 195 CFArrayRef oldPreferences; 196 CFStringRef str; 197 CFStringRef trace; 198 struct tm tm_now; 199 struct timeval tv_now; 200 201 bVal = CFPreferencesCopyAppValue(CFSTR("LOG_SC_CHANGES"), USER_PREFERENCES_APPLICATION_ID); 202 if (bVal != NULL) { 203 Boolean enabled; 204 205 enabled = isA_CFBoolean(bVal) && CFBooleanGetValue(bVal); 206 CFRelease(bVal); 207 if (!enabled) { 208 // if debugging not enabled 209 return; 210 } 211 } else { 212 // if debugging not enabled 213 return; 214 } 215 216 (void)gettimeofday(&tv_now, NULL); 217 (void)localtime_r(&tv_now.tv_sec, &tm_now); 218 219 str = CFStringCreateWithFormat(NULL, NULL, 220 CFSTR("/var/tmp/com.apple.networkConnect-%@-%4d%02d%02d.%02d%02d%02d.%03d"), 221 serviceID, 222 tm_now.tm_year + 1900, 223 tm_now.tm_mon + 1, 224 tm_now.tm_mday, 225 tm_now.tm_hour, 226 tm_now.tm_min, 227 tm_now.tm_sec, 228 tv_now.tv_usec / 1000); 229 _SC_cfstring_to_cstring(str, dir, sizeof(dir), kCFStringEncodingUTF8); 230 CFRelease(str); 231 232 SC_log(LOG_NOTICE, "CFPreferences being updated, old/new in \"%s\"", dir); 233 234 if (mkdir(dir, 0755) == -1) { 235 SC_log(LOG_NOTICE, "mkdir() failed: %s", SCErrorString(errno)); 236 return; 237 } 238 239 trace = _SC_copyBacktrace(); 240 if (trace != NULL) { 241 FILE *f; 242 int fd; 243 char path[256]; 244 245 strlcpy(path, dir, sizeof(path)); 246 strlcat(path, "/backtrace", sizeof(path)); 247 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 248 if (fd == -1) { 249 SC_log(LOG_NOTICE, "fopen() failed: %s", SCErrorString(errno)); 250 CFRelease(trace); 251 return; 252 } 253 f = fdopen(fd, "w"); 254 SCPrint(TRUE, f, CFSTR("%@"), trace); 255 (void) fclose(f); 256 CFRelease(trace); 257 } 258 259 oldPreferences = CFPreferencesCopyAppValue(serviceID, USER_PREFERENCES_APPLICATION_ID); 260 if (oldPreferences != NULL) { 261 int fd; 262 CFDataRef data; 263 char path[256]; 264 265 strlcpy(path, dir, sizeof(path)); 266 strlcat(path, "/old", sizeof(path)); 267 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 268 if (fd == -1) { 269 SC_log(LOG_NOTICE, "fopen() failed: %s", SCErrorString(errno)); 270 CFRelease(oldPreferences); 271 return; 272 } 273 data = CFPropertyListCreateData(NULL, oldPreferences, kCFPropertyListXMLFormat_v1_0, 0, NULL); 274 if (data == NULL) { 275 SC_log(LOG_NOTICE, "CFPropertyListCreateData() failed"); 276 close(fd); 277 CFRelease(oldPreferences); 278 return; 279 } 280 (void) write(fd, CFDataGetBytePtr(data), CFDataGetLength(data)); 281 (void) close(fd); 282 CFRelease(data); 283 CFRelease(oldPreferences); 284 } 285 286 if (newPreferences != NULL) { 287 int fd; 288 CFDataRef data; 289 char path[256]; 290 291 strlcpy(path, dir, sizeof(path)); 292 strlcat(path, "/new", sizeof(path)); 293 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 294 if (fd == -1) { 295 SC_log(LOG_NOTICE, "fopen() failed: %s", SCErrorString(errno)); 296 return; 297 } 298 data = CFPropertyListCreateData(NULL, newPreferences, kCFPropertyListXMLFormat_v1_0, 0, NULL); 299 if (data == NULL) { 300 SC_log(LOG_NOTICE, "CFPropertyListCreateData() failed"); 301 close(fd); 302 return; 303 } 304 (void) write(fd, CFDataGetBytePtr(data), CFDataGetLength(data)); 305 (void) close(fd); 306 CFRelease(data); 307 } 308 309 return; 310} 311#endif // LOG_CFPREFERENCES_CHANGES 312 313 314static CFArrayRef 315copyCFPreferencesForServiceID(CFStringRef serviceID) 316{ 317 CFArrayRef prefs; 318 319 // fetch "Managed" or "ByHost" user preferences 320 (void) CFPreferencesAppSynchronize(USER_PREFERENCES_APPLICATION_ID); 321 prefs = CFPreferencesCopyAppValue(serviceID, 322 USER_PREFERENCES_APPLICATION_ID); 323 324 if ((prefs != NULL) && !isA_CFArray(prefs)) { 325 CFRelease(prefs); 326 return NULL; 327 } 328 329 return prefs; 330} 331 332 333static Boolean 334setCFPreferencesForServiceID(CFStringRef serviceID, CFArrayRef newPreferences) 335{ 336 Boolean ok; 337 338 if (CFPreferencesAppValueIsForced(serviceID, USER_PREFERENCES_APPLICATION_ID)) { 339 return FALSE; 340 } 341 342#ifdef LOG_CFPREFERENCES_CHANGES 343 logCFPreferencesChange(serviceID, newPreferences); 344#endif // LOG_CFPREFERENCES_CHANGES 345 346 CFPreferencesSetValue(serviceID, 347 newPreferences, 348 USER_PREFERENCES_APPLICATION_ID, 349 kCFPreferencesCurrentUser, 350 kCFPreferencesCurrentHost); 351 ok = CFPreferencesSynchronize(USER_PREFERENCES_APPLICATION_ID, 352 kCFPreferencesCurrentUser, 353 kCFPreferencesCurrentHost); 354 355 (void) notify_post(USER_PREFERENCES_NOTIFICATION); 356 357 return ok; 358} 359 360 361static void 362addPreference(CFMutableArrayRef *newPrefs, CFDictionaryRef newDict) 363{ 364 if (*newPrefs == NULL) { 365 *newPrefs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 366 } 367 CFArrayAppendValue(*newPrefs, newDict); 368 369 return; 370} 371 372 373typedef CFDictionaryRef (*processPreferencesCallout) (CFStringRef serviceID, 374 CFDictionaryRef current, 375 void *context1, 376 void *context2, 377 void *context3); 378 379 380static Boolean 381processPreferences(CFStringRef serviceID, 382 processPreferencesCallout callout, 383 void *context1, 384 void *context2, 385 void *context3) 386{ 387 Boolean changed = FALSE; 388 CFIndex i; 389 CFIndex n; 390 CFDictionaryRef newDict = NULL; 391 CFMutableArrayRef newPrefs = NULL; 392 Boolean ok = TRUE; 393 CFArrayRef prefs; 394 395 prefs = copyCFPreferencesForServiceID(serviceID); 396 n = (prefs != NULL) ? CFArrayGetCount(prefs) : 0; 397 for (i = 0; i < n; i++) { 398 CFDictionaryRef dict; 399 400 dict = CFArrayGetValueAtIndex(prefs, i); 401 assert(dict != NULL); 402 if (isA_CFDictionary(dict)) { 403 newDict = (*callout)(serviceID, dict, context1, context2, context3); 404 if (newDict == NULL) { 405 // if entry to be removed 406 changed = TRUE; 407 continue; 408 } 409 } else { 410 // if not a CFDictionary, leave as-is 411 newDict = CFRetain(dict); 412 } 413 414 if (!CFEqual(dict, newDict)) { 415 changed = TRUE; 416 } 417 418 addPreference(&newPrefs, newDict); 419 CFRelease(newDict); 420 } 421 if (prefs != NULL) CFRelease(prefs); 422 423 newDict = (*callout)(serviceID, NULL, context1, context2, context3); 424 if (newDict != NULL) { 425 // if new entry 426 changed = TRUE; 427 addPreference(&newPrefs, newDict); 428 CFRelease(newDict); 429 } 430 431 if (changed) { 432 ok = setCFPreferencesForServiceID(serviceID, newPrefs); 433 } 434 if (newPrefs != NULL) CFRelease(newPrefs); 435 436 return ok; 437} 438 439 440static __inline__ Boolean 441isMatchingPrefsID(CFDictionaryRef dict, CFStringRef matchID) 442{ 443 CFStringRef prefsID; 444 445 prefsID = CFDictionaryGetValue(dict, USER_PREFERENCES_ID); 446 if (isA_CFString(prefsID)) { 447 if (CFEqual(prefsID, matchID)) { 448 return TRUE; 449 } 450 } 451 452 return FALSE; 453} 454 455 456CFTypeID 457SCUserPreferencesGetTypeID(void) 458{ 459 pthread_once(&initialized, __SCUserPreferencesInitialize); /* initialize runtime */ 460 return __kSCUserPreferencesTypeID; 461} 462 463 464CFStringRef 465SCUserPreferencesGetUniqueID(SCUserPreferencesRef userPreferences) 466{ 467 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 468 469 if (!isA_SCUserPreferences(userPreferences)) { 470 _SCErrorSet(kSCStatusInvalidArgument); 471 return FALSE; 472 } 473 474 return userPrivate->prefsID; 475} 476 477 478Boolean 479SCUserPreferencesIsForced(SCUserPreferencesRef userPreferences) 480{ 481 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 482 483 if (!isA_SCUserPreferences(userPreferences)) { 484 _SCErrorSet(kSCStatusInvalidArgument); 485 return FALSE; 486 } 487 488 return CFPreferencesAppValueIsForced(userPrivate->serviceID, USER_PREFERENCES_APPLICATION_ID); 489} 490 491 492static CFDictionaryRef 493removeCallout(CFStringRef serviceID, 494 CFDictionaryRef current, 495 void *context1, 496 void *context2, 497 void *context3) 498{ 499#pragma unused(serviceID) 500#pragma unused(context2) 501#pragma unused(context3) 502 CFStringRef matchID = (CFStringRef)context1; 503 504 if (current == NULL) { 505 // we have nothing to "add" 506 return NULL; 507 } 508 509 if (isMatchingPrefsID(current, matchID)) { 510 // if we match, don't add (i.e. remove) 511 return NULL; 512 } 513 514 return CFRetain(current); 515} 516 517 518Boolean 519SCUserPreferencesRemove(SCUserPreferencesRef userPreferences) 520{ 521 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 522 523 if (!isA_SCUserPreferences(userPreferences)) { 524 _SCErrorSet(kSCStatusInvalidArgument); 525 return FALSE; 526 } 527 528 return processPreferences(userPrivate->serviceID, 529 removeCallout, 530 (void *)userPrivate->prefsID, 531 NULL, 532 NULL); 533} 534 535 536static CF_RETURNS_RETAINED CFDictionaryRef 537setCurrentCallout(CFStringRef serviceID, 538 CFDictionaryRef current, 539 void *context1, 540 void *context2, 541 void *context3) 542{ 543#pragma unused(serviceID) 544#pragma unused(context2) 545#pragma unused(context3) 546 CFStringRef matchID = (CFStringRef)context1; 547 CFMutableDictionaryRef newDict; 548 549 if (current == NULL) { 550 // we have nothing to "add" 551 return NULL; 552 } 553 554 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current); 555 556 // remove "default" flag 557 CFDictionaryRemoveValue(newDict, USER_PREFERENCES_DEFAULT); 558 559 if (isMatchingPrefsID(current, matchID)) { 560 // if we match, set "default" flag 561 CFDictionarySetValue(newDict, USER_PREFERENCES_DEFAULT, kCFBooleanTrue); 562 } 563 564 return newDict; 565} 566 567 568Boolean 569SCUserPreferencesSetCurrent(SCUserPreferencesRef userPreferences) 570{ 571 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 572 573 if (!isA_SCUserPreferences(userPreferences)) { 574 _SCErrorSet(kSCStatusInvalidArgument); 575 return FALSE; 576 } 577 578 return processPreferences(userPrivate->serviceID, 579 setCurrentCallout, 580 (void *)userPrivate->prefsID, 581 NULL, 582 NULL); 583} 584 585 586static CFDictionaryRef 587copyNameCallout(CFStringRef serviceID, 588 CFDictionaryRef current, 589 void *context1, 590 void *context2, 591 void *context3) 592{ 593#pragma unused(serviceID) 594#pragma unused(context2) 595#pragma unused(context3) 596 CFStringRef matchID = (CFStringRef)context1; 597 CFStringRef *name = (CFStringRef *)context3; 598 599 if (current == NULL) { 600 // we have nothing to "add" 601 return NULL; 602 } 603 604 if (isMatchingPrefsID(current, matchID)) { 605 if (*name != NULL) { 606 CFRelease(*name); 607 *name = NULL; 608 } 609 *name = CFDictionaryGetValue(current, kSCPropUserDefinedName); 610 611 // for backwards compatibility, we also check for the name in the PPP entity 612 if (*name == NULL) { 613 CFDictionaryRef ppp; 614 615 ppp = CFDictionaryGetValue(current, kSCEntNetPPP); 616 if (isA_CFDictionary(ppp)) { 617 *name = CFDictionaryGetValue(ppp, kSCPropUserDefinedName); 618 } 619 } 620 621 *name = isA_CFString(*name); 622 if (*name != NULL) { 623 CFRetain(*name); 624 } 625 } 626 627 return CFRetain(current); 628} 629 630 631CFStringRef 632SCUserPreferencesCopyName(SCUserPreferencesRef userPreferences) 633{ 634 CFStringRef name = NULL; 635 Boolean ok; 636 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 637 638 if (!isA_SCUserPreferences(userPreferences)) { 639 _SCErrorSet(kSCStatusInvalidArgument); 640 return FALSE; 641 } 642 643 // find SCUserPreferences and copy name 644 ok = processPreferences(userPrivate->serviceID, 645 copyNameCallout, 646 (void *)userPrivate->prefsID, 647 NULL, 648 (void *)&name); 649 if (!ok) { 650 if (name != NULL) { 651 CFRelease(name); 652 name = NULL; 653 } 654 } 655 656 return name; 657} 658 659 660static CF_RETURNS_RETAINED CFDictionaryRef 661setNameCallout(CFStringRef serviceID, 662 CFDictionaryRef current, 663 void *context1, 664 void *context2, 665 void *context3) 666{ 667#pragma unused(serviceID) 668#pragma unused(context2) 669#pragma unused(context3) 670 CFStringRef matchID = (CFStringRef)context1; 671 CFMutableDictionaryRef newDict; 672 CFStringRef newName = (CFStringRef)context2; 673 674 if (current == NULL) { 675 // we have nothing to "add" 676 return NULL; 677 } 678 679 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current); 680 681 if (isMatchingPrefsID(current, matchID)) { 682 CFDictionaryRef pppEntity; 683 684 // set the name 685 if (newName != NULL) { 686 CFDictionarySetValue(newDict, kSCPropUserDefinedName, newName); 687 } else { 688 CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName); 689 } 690 691 // for backwards compatibility, we also set the name in the PPP entity 692 pppEntity = CFDictionaryGetValue(newDict, kSCEntNetPPP); 693 if (isA_CFDictionary(pppEntity)) { 694 CFMutableDictionaryRef newPPPEntity; 695 696 newPPPEntity = CFDictionaryCreateMutableCopy(NULL, 0, pppEntity); 697 if (newName != NULL) { 698 CFDictionarySetValue(newPPPEntity, kSCPropUserDefinedName, newName); 699 } else { 700 CFDictionaryRemoveValue(newPPPEntity, kSCPropUserDefinedName); 701 } 702 CFDictionarySetValue(newDict, kSCEntNetPPP, newPPPEntity); 703 CFRelease(newPPPEntity); 704 } 705 } 706 707 return newDict; 708} 709 710 711Boolean 712SCUserPreferencesSetName(SCUserPreferencesRef userPreferences, CFStringRef newName) 713{ 714 Boolean ok; 715 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 716 717 if (!isA_SCUserPreferences(userPreferences)) { 718 _SCErrorSet(kSCStatusInvalidArgument); 719 return FALSE; 720 } 721 722 if ((newName != NULL) && !isA_CFString(newName)) { 723 _SCErrorSet(kSCStatusInvalidArgument); 724 return FALSE; 725 } 726 727 // find SCUserPreferences and set name 728 ok = processPreferences(userPrivate->serviceID, 729 setNameCallout, 730 (void *)userPrivate->prefsID, 731 (void *)newName, 732 NULL); 733 734 return ok; 735} 736 737 738static CFDictionaryRef 739copyInterfaceConfigurationCallout(CFStringRef serviceID, 740 CFDictionaryRef current, 741 void *context1, 742 void *context2, 743 void *context3) 744{ 745#pragma unused(serviceID) 746 CFDictionaryRef *dict = (CFDictionaryRef *)context3; 747 CFStringRef interfaceType = (CFStringRef)context2; 748 CFStringRef matchID = (CFStringRef)context1; 749 750 if (current == NULL) { 751 // we have nothing to "add" 752 return NULL; 753 } 754 755 if (isMatchingPrefsID(current, matchID)) { 756 if (*dict != NULL) { 757 CFRelease(*dict); 758 *dict = NULL; 759 } 760 *dict = CFDictionaryGetValue(current, interfaceType); 761 *dict = isA_CFDictionary(*dict); 762 if (*dict != NULL) { 763 CFRetain(*dict); 764 } 765 } 766 767 return CFRetain(current); 768} 769 770 771CFDictionaryRef 772SCUserPreferencesCopyInterfaceConfiguration(SCUserPreferencesRef userPreferences, 773 SCNetworkInterfaceRef interface) 774{ 775 CFStringRef defaultType; 776 CFDictionaryRef entity = NULL; 777 Boolean ok; 778 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 779 780 if (!isA_SCUserPreferences(userPreferences)) { 781 _SCErrorSet(kSCStatusInvalidArgument); 782 return NULL; 783 } 784 785 if (!isA_SCNetworkInterface(interface)) { 786 _SCErrorSet(kSCStatusInvalidArgument); 787 return NULL; 788 } 789 790 // get InterfaceType 791 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 792 if (defaultType == NULL) { 793 _SCErrorSet(kSCStatusInvalidArgument); 794 return NULL; 795 } 796 797 // find SCUserPreferences and copy interface entity 798 ok = processPreferences(userPrivate->serviceID, 799 copyInterfaceConfigurationCallout, 800 (void *)userPrivate->prefsID, 801 (void *)defaultType, 802 (void *)&entity); 803 if (!ok) { 804 if (entity != NULL) { 805 CFRelease(entity); 806 entity = NULL; 807 } 808 } 809 810 return entity; 811} 812 813 814static CF_RETURNS_RETAINED CFDictionaryRef 815setInterfaceConfigurationCallout(CFStringRef serviceID, 816 CFDictionaryRef current, 817 void *context1, 818 void *context2, 819 void *context3) 820{ 821#pragma unused(serviceID) 822 CFStringRef interfaceType = (CFStringRef)context2; 823 CFStringRef matchID = (CFStringRef)context1; 824 CFMutableDictionaryRef newDict; 825 CFDictionaryRef newOptions = (CFDictionaryRef)context3; 826 827 if (current == NULL) { 828 // we have nothing to "add" 829 return NULL; 830 } 831 832 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current); 833 834 if (isMatchingPrefsID(current, matchID)) { 835 if (newOptions != NULL) { 836 CFDictionarySetValue(newDict, interfaceType, newOptions); 837 838 // for backwards compatibility, we want to ensure that 839 // the name is set in both the top level and in the PPP 840 // entity. 841 if (CFEqual(interfaceType, kSCEntNetPPP)) { 842 CFStringRef name; 843 844 name = CFDictionaryGetValue(newOptions, kSCPropUserDefinedName); 845 if (name != NULL) { 846 // if name was passed in newOptions, push up 847 CFDictionarySetValue(newDict, kSCPropUserDefinedName, name); 848 } else { 849 name = CFDictionaryGetValue(newDict, kSCPropUserDefinedName); 850 if (name != NULL) { 851 CFMutableDictionaryRef newPPPEntity; 852 853 // if name in parent, push into entity 854 newPPPEntity = CFDictionaryCreateMutableCopy(NULL, 0, newOptions); 855 CFDictionarySetValue(newPPPEntity, kSCPropUserDefinedName, name); 856 CFDictionarySetValue(newDict, interfaceType, newPPPEntity); 857 CFRelease(newPPPEntity); 858 } 859 } 860 } 861 } else { 862 CFDictionaryRemoveValue(newDict, interfaceType); 863 } 864 } 865 866 return newDict; 867} 868 869 870Boolean 871SCUserPreferencesSetInterfaceConfiguration(SCUserPreferencesRef userPreferences, 872 SCNetworkInterfaceRef interface, 873 CFDictionaryRef newOptions) 874{ 875 CFStringRef defaultType; 876 Boolean ok; 877 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 878 879 if (!isA_SCUserPreferences(userPreferences)) { 880 _SCErrorSet(kSCStatusInvalidArgument); 881 return FALSE; 882 } 883 884 if (!isA_SCNetworkInterface(interface)) { 885 _SCErrorSet(kSCStatusInvalidArgument); 886 return FALSE; 887 } 888 889 // get InterfaceType 890 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface); 891 if (defaultType == NULL) { 892 _SCErrorSet(kSCStatusInvalidArgument); 893 return FALSE; 894 } 895 896 // set new interface entity for SCUserPreferences 897 ok = processPreferences(userPrivate->serviceID, 898 setInterfaceConfigurationCallout, 899 (void *)userPrivate->prefsID, 900 (void *)defaultType, 901 (void *)newOptions); 902 903 return ok; 904} 905 906 907CFDictionaryRef 908SCUserPreferencesCopyExtendedInterfaceConfiguration(SCUserPreferencesRef userPreferences, 909 SCNetworkInterfaceRef interface, 910 CFStringRef extendedType) 911{ 912 CFDictionaryRef entity = NULL; 913 Boolean ok; 914 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 915 916 if (!isA_SCUserPreferences(userPreferences)) { 917 _SCErrorSet(kSCStatusInvalidArgument); 918 return NULL; 919 } 920 921 if (!isA_SCNetworkInterface(interface)) { 922 _SCErrorSet(kSCStatusInvalidArgument); 923 return NULL; 924 } 925 926 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, FALSE)) { 927 _SCErrorSet(kSCStatusInvalidArgument); 928 return NULL; 929 } 930 931 // find SCUserPreferences and copy interface entity 932 ok = processPreferences(userPrivate->serviceID, 933 copyInterfaceConfigurationCallout, 934 (void *)userPrivate->prefsID, 935 (void *)extendedType, 936 (void *)&entity); 937 if (!ok) { 938 if (entity != NULL) { 939 CFRelease(entity); 940 entity = NULL; 941 } 942 } 943 944 return entity; 945} 946 947 948Boolean 949SCUserPreferencesSetExtendedInterfaceConfiguration(SCUserPreferencesRef userPreferences, 950 SCNetworkInterfaceRef interface, 951 CFStringRef extendedType, 952 CFDictionaryRef newOptions) 953{ 954 Boolean ok; 955 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 956 957 if (!isA_SCUserPreferences(userPreferences)) { 958 _SCErrorSet(kSCStatusInvalidArgument); 959 return FALSE; 960 } 961 962 if (!isA_SCNetworkInterface(interface)) { 963 _SCErrorSet(kSCStatusInvalidArgument); 964 return FALSE; 965 } 966 967 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, FALSE)) { 968 _SCErrorSet(kSCStatusInvalidArgument); 969 return FALSE; 970 } 971 972 // set new interface entity for SCUserPreferences 973 ok = processPreferences(userPrivate->serviceID, 974 setInterfaceConfigurationCallout, 975 (void *)userPrivate->prefsID, 976 (void *)extendedType, 977 (void *)newOptions); 978 979 return ok; 980} 981 982 983#pragma mark - 984#pragma mark SCNetworkConnection + SCUserPreferences SPIs 985 986 987static CFDictionaryRef 988copyAllCallout(CFStringRef serviceID, 989 CFDictionaryRef current, 990 void *context1, 991 void *context2, 992 void *context3) 993{ 994#pragma unused(context1) 995#pragma unused(context2) 996 CFMutableArrayRef *prefs = (CFMutableArrayRef *)context3; 997 CFStringRef prefsID; 998 SCUserPreferencesPrivateRef userPrivate; 999 1000 if (current == NULL) { 1001 // we have nothing to "add" 1002 return NULL; 1003 } 1004 1005 prefsID = CFDictionaryGetValue(current, USER_PREFERENCES_ID); 1006 if (!isA_CFString(prefsID)) { 1007 // if no unique ID 1008 goto done; 1009 } 1010 1011 userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, prefsID); 1012 if (userPrivate != NULL) { 1013 if (*prefs == NULL) { 1014 *prefs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1015 } 1016 CFArrayAppendValue(*prefs, (SCUserPreferencesRef)userPrivate); 1017 CFRelease(userPrivate); 1018 } 1019 1020 done : 1021 1022 return CFRetain(current); 1023} 1024 1025 1026CFArrayRef /* of SCUserPreferencesRef's */ 1027SCNetworkConnectionCopyAllUserPreferences(SCNetworkConnectionRef connection) 1028{ 1029 Boolean ok; 1030 CFMutableArrayRef prefs = NULL; 1031 CFStringRef serviceID; 1032 1033 // get serviceID 1034 serviceID = SCNetworkConnectionCopyServiceID(connection); 1035 1036 // collect SCUserPreferences 1037 ok = processPreferences(serviceID, 1038 copyAllCallout, 1039 NULL, 1040 NULL, 1041 (void *)&prefs); 1042 if (!ok) { 1043 if (prefs != NULL) { 1044 CFRelease(prefs); 1045 prefs = NULL; 1046 } 1047 } 1048 1049 CFRelease(serviceID); 1050 return prefs; 1051} 1052 1053 1054static CFDictionaryRef 1055copyCurrentCallout(CFStringRef serviceID, 1056 CFDictionaryRef current, 1057 void *context1, 1058 void *context2, 1059 void *context3) 1060{ 1061#pragma unused(context1) 1062#pragma unused(context2) 1063 CFBooleanRef isDefault; 1064 CFStringRef prefsID; 1065 SCUserPreferencesPrivateRef *userPrivate = (SCUserPreferencesPrivateRef *)context3; 1066 1067 if (current == NULL) { 1068 // we have nothing to "add" 1069 return NULL; 1070 } 1071 1072 prefsID = CFDictionaryGetValue(current, USER_PREFERENCES_ID); 1073 if (!isA_CFString(prefsID)) { 1074 // if no unique ID 1075 goto done; 1076 } 1077 1078 isDefault = CFDictionaryGetValue(current, USER_PREFERENCES_DEFAULT); 1079 if (!isA_CFBoolean(isDefault) || !CFBooleanGetValue(isDefault)) { 1080 // if not the default configuration 1081 goto done; 1082 } 1083 1084 *userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, prefsID); 1085 1086 done : 1087 1088 return CFRetain(current); 1089} 1090 1091 1092SCUserPreferencesRef 1093SCNetworkConnectionCopyCurrentUserPreferences(SCNetworkConnectionRef connection) 1094{ 1095 SCUserPreferencesRef current = NULL; 1096 Boolean ok; 1097 CFStringRef serviceID; 1098 1099 // get serviceID 1100 serviceID = SCNetworkConnectionCopyServiceID(connection); 1101 1102 // collect SCUserPreferences 1103 ok = processPreferences(serviceID, 1104 copyCurrentCallout, 1105 NULL, 1106 NULL, 1107 (void *)&current); 1108 if (!ok) { 1109 if (current != NULL) { 1110 CFRelease(current); 1111 current = NULL; 1112 } 1113 } 1114 1115 CFRelease(serviceID); 1116 return current; 1117} 1118 1119 1120static CFDictionaryRef 1121createCallout(CFStringRef serviceID, 1122 CFDictionaryRef current, 1123 void *context1, 1124 void *context2, 1125 void *context3) 1126{ 1127#pragma unused(serviceID) 1128#pragma unused(context2) 1129#pragma unused(context3) 1130 CFMutableDictionaryRef newDict; 1131 CFStringRef newPrefsID = (CFStringRef)context1; 1132 1133 if (current != NULL) { 1134 // don't change existing entries 1135 return CFRetain(current); 1136 } 1137 1138 newDict = CFDictionaryCreateMutable(NULL, 1139 0, 1140 &kCFTypeDictionaryKeyCallBacks, 1141 &kCFTypeDictionaryValueCallBacks); 1142 CFDictionarySetValue(newDict, USER_PREFERENCES_ID, newPrefsID); 1143 return newDict; 1144} 1145 1146 1147SCUserPreferencesRef 1148SCNetworkConnectionCreateUserPreferences(SCNetworkConnectionRef connection) 1149{ 1150 CFStringRef newPrefsID; 1151 CFStringRef serviceID; 1152 SCUserPreferencesPrivateRef userPrivate; 1153 CFUUIDRef uuid; 1154 1155 // get serviceID 1156 serviceID = SCNetworkConnectionCopyServiceID(connection); 1157 1158 // allocate a new user preferences ID 1159 uuid = CFUUIDCreate(NULL); 1160 newPrefsID = CFUUIDCreateString(NULL, uuid); 1161 CFRelease(uuid); 1162 1163 userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, newPrefsID); 1164 if (userPrivate != NULL) { 1165 (void) processPreferences(serviceID, 1166 createCallout, 1167 (void *)newPrefsID, 1168 NULL, 1169 NULL); 1170 } 1171 1172 CFRelease(newPrefsID); 1173 CFRelease(serviceID); 1174 return (SCUserPreferencesRef)userPrivate; 1175} 1176 1177 1178static void 1179update_PPP_entity(SCUserPreferencesRef userPreferences, CFDictionaryRef *userOptions) 1180{ 1181 CFStringRef encryption; 1182 CFDictionaryRef entity; 1183 CFStringRef keychainID; 1184 1185 entity = CFDictionaryGetValue(*userOptions, kSCEntNetPPP); 1186 if (!isA_CFDictionary(entity)) { 1187 return; 1188 } 1189 1190 encryption = CFDictionaryGetValue(entity, kSCPropNetPPPAuthPasswordEncryption); 1191 if (encryption == NULL) { 1192 // provide default encryption method 1193 encryption = kSCValNetPPPAuthPasswordEncryptionKeychain; 1194 } 1195 1196 if (!isA_CFString(encryption) || 1197 !CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) { 1198 return; 1199 } 1200 1201 keychainID = CFDictionaryGetValue(entity, kSCPropNetPPPAuthPassword); 1202 if (isA_CFString(keychainID)) { 1203 // if password is keychain ID 1204 } else if (isA_CFData(keychainID) && 1205 ((CFDataGetLength((CFDataRef)keychainID) % sizeof(UniChar)) == 0)) { 1206 // if inline password 1207 return; 1208 } else { 1209 keychainID = SCUserPreferencesGetUniqueID(userPreferences); 1210 } 1211 1212 if (_SCSecKeychainPasswordItemExists(NULL, keychainID)) { 1213 CFMutableDictionaryRef new_entity; 1214 CFMutableDictionaryRef new_options; 1215 1216 // access PPP password from system keychain 1217 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity); 1218 1219 CFDictionarySetValue(new_entity, 1220 kSCPropNetPPPAuthPassword, 1221 keychainID); 1222 CFDictionarySetValue(new_entity, 1223 kSCPropNetPPPAuthPasswordEncryption, 1224 kSCValNetPPPAuthPasswordEncryptionKeychain); 1225 1226 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions); 1227 CFDictionarySetValue(new_options, kSCEntNetPPP, new_entity); 1228 CFRelease(new_entity); 1229 1230 CFRelease(*userOptions); 1231 *userOptions = new_options; 1232 } 1233 1234 return; 1235} 1236 1237 1238static void 1239update_IPSec_entity(SCUserPreferencesRef userPreferences, CFDictionaryRef *userOptions) 1240{ 1241 CFStringRef encryption; 1242 CFDictionaryRef entity; 1243 SecKeychainRef keychain = NULL; 1244 CFStringRef keychainID; 1245 CFStringRef method; 1246 CFDataRef sharedSecret; 1247 1248 entity = CFDictionaryGetValue(*userOptions, kSCEntNetIPSec); 1249 if (!isA_CFDictionary(entity)) { 1250 return; 1251 } 1252 1253 method = CFDictionaryGetValue(entity, kSCPropNetIPSecAuthenticationMethod); 1254 if (!isA_CFString(method) || 1255 !CFEqual(method, kSCValNetIPSecAuthenticationMethodSharedSecret)) { 1256 return; 1257 } 1258 1259 encryption = CFDictionaryGetValue(entity, kSCPropNetIPSecSharedSecretEncryption); 1260 if (encryption == NULL) { 1261 // provide default encryption method 1262 encryption = kSCValNetIPSecSharedSecretEncryptionKeychain; 1263 } 1264 1265 if (!isA_CFString(encryption) || 1266 !CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) { 1267 return; 1268 } 1269 1270 keychainID = CFDictionaryGetValue(entity, kSCPropNetIPSecSharedSecret); 1271 if (isA_CFString(keychainID)) { 1272 // if shared secret is keychain ID 1273 CFRetain(keychainID); 1274 } else if (isA_CFData(keychainID) && 1275 ((CFDataGetLength((CFDataRef)keychainID) % sizeof(UniChar)) == 0)) { 1276 // if inline shared secret 1277 return; 1278 } else { 1279 CFStringRef unique_id; 1280 1281 unique_id = SCUserPreferencesGetUniqueID(userPreferences); 1282 keychainID = (CFStringRef)CFStringCreateMutableCopy(NULL, 0, unique_id); 1283 CFStringAppend((CFMutableStringRef)keychainID, CFSTR(".SS")); 1284 } 1285 1286 sharedSecret = _SCSecKeychainPasswordItemCopy(NULL, keychainID); 1287 if (sharedSecret != NULL) { 1288 CFMutableDictionaryRef new_entity; 1289 CFMutableDictionaryRef new_options; 1290 CFStringRef password; 1291 1292 // pass SharedSecret from user keychain 1293 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity); 1294 1295 password = CFStringCreateWithBytes(NULL, 1296 CFDataGetBytePtr(sharedSecret), 1297 CFDataGetLength(sharedSecret), 1298 kCFStringEncodingUTF8, 1299 FALSE); 1300 CFRelease(sharedSecret); 1301 CFDictionarySetValue(new_entity, 1302 kSCPropNetIPSecSharedSecret, 1303 password); 1304 CFRelease(password); 1305 CFDictionaryRemoveValue(new_entity, 1306 kSCPropNetIPSecSharedSecretEncryption); 1307 1308 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions); 1309 CFDictionarySetValue(new_options, kSCEntNetIPSec, new_entity); 1310 CFRelease(new_entity); 1311 1312 CFRelease(*userOptions); 1313 *userOptions = new_options; 1314 goto done; 1315 } 1316 1317 keychain = _SCSecKeychainCopySystemKeychain(); 1318 if (keychain == NULL) { 1319 goto done; 1320 } 1321 1322 if (_SCSecKeychainPasswordItemExists(keychain, keychainID)) { 1323 CFMutableDictionaryRef new_entity; 1324 CFMutableDictionaryRef new_options; 1325 1326 // access SharedSecret from system keychain 1327 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity); 1328 1329 CFDictionarySetValue(new_entity, 1330 kSCPropNetIPSecSharedSecret, 1331 keychainID); 1332 CFDictionarySetValue(new_entity, 1333 kSCPropNetIPSecSharedSecretEncryption, 1334 kSCValNetIPSecSharedSecretEncryptionKeychain); 1335 1336 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions); 1337 CFDictionarySetValue(new_options, kSCEntNetIPSec, new_entity); 1338 CFRelease(new_entity); 1339 1340 CFRelease(*userOptions); 1341 *userOptions = new_options; 1342 } 1343 1344 done : 1345 1346 if (keychain != NULL) CFRelease(keychain); 1347 CFRelease(keychainID); 1348 return; 1349} 1350 1351 1352static CFDictionaryRef 1353copyOptionsCallout(CFStringRef serviceID, 1354 CFDictionaryRef current, 1355 void *context1, 1356 void *context2, 1357 void *context3) 1358{ 1359#pragma unused(serviceID) 1360#pragma unused(context2) 1361 CFStringRef matchID = (CFStringRef)context1; 1362 CFMutableDictionaryRef *userOptions = (CFMutableDictionaryRef *)context3; 1363 1364 if (current == NULL) { 1365 // we have nothing to "add" 1366 return NULL; 1367 } 1368 1369 if (isMatchingPrefsID(current, matchID)) { 1370 // if we match, return options dictionary 1371 if (*userOptions != NULL) CFRelease(*userOptions); 1372 *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, current); 1373 CFDictionaryRemoveValue(*userOptions, USER_PREFERENCES_ID); 1374 CFDictionaryRemoveValue(*userOptions, USER_PREFERENCES_DEFAULT); 1375 } 1376 1377 return CFRetain(current); 1378} 1379 1380 1381Boolean 1382SCNetworkConnectionStartWithUserPreferences(SCNetworkConnectionRef connection, 1383 SCUserPreferencesRef userPreferences, 1384 Boolean linger) 1385{ 1386 Boolean ok; 1387 CFDictionaryRef userOptions = NULL; 1388 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences; 1389 1390 if (!isA_SCUserPreferences(userPreferences)) { 1391 _SCErrorSet(kSCStatusInvalidArgument); 1392 return FALSE; 1393 } 1394 1395 (void) processPreferences(userPrivate->serviceID, 1396 copyOptionsCallout, 1397 (void *)userPrivate->prefsID, 1398 NULL, 1399 &userOptions); 1400 1401 /* 1402 * For some legacy preferences, some of the user options 1403 * were missing yet handled by the APIs. Make sure that 1404 * everything still works! 1405 */ 1406 if (userOptions != NULL) { 1407 update_PPP_entity (userPreferences, &userOptions); 1408 update_IPSec_entity(userPreferences, &userOptions); 1409 } 1410 1411 ok = SCNetworkConnectionStart(connection, userOptions, linger); 1412 1413 if (userOptions != NULL) { 1414 CFRelease(userOptions); 1415 } 1416 1417 return ok; 1418} 1419 1420 1421#pragma mark - 1422#pragma mark SCUserPreferences + SCNetworkInterface Password SPIs 1423 1424 1425static CFStringRef 1426getUserPasswordID(CFDictionaryRef config, SCUserPreferencesRef userPreferences) 1427{ 1428 CFStringRef unique_id = NULL; 1429 1430 if (config != NULL) { 1431 CFStringRef encryption; 1432 1433 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption); 1434 if (isA_CFString(encryption) && 1435 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) { 1436 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword); 1437 } 1438 } 1439 if (unique_id == NULL) { 1440 unique_id = SCUserPreferencesGetUniqueID(userPreferences); 1441 } 1442 1443 return unique_id; 1444} 1445 1446 1447static CFStringRef 1448copyUserSharedSecretID(CFDictionaryRef config, SCUserPreferencesRef userPreferences) 1449{ 1450 CFMutableStringRef sharedSecret = NULL; 1451 1452 if (config != NULL) { 1453 CFStringRef encryption; 1454 1455 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption); 1456 if (isA_CFString(encryption) && 1457 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) { 1458 sharedSecret = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret); 1459 if (sharedSecret != NULL) { 1460 CFRetain(sharedSecret); 1461 } 1462 } 1463 } 1464 1465 if (sharedSecret == NULL) { 1466 CFStringRef unique_id; 1467 1468 unique_id = getUserPasswordID(config, userPreferences); 1469 sharedSecret = CFStringCreateMutableCopy(NULL, 0, unique_id); 1470 CFStringAppend(sharedSecret, CFSTR(".SS")); 1471 } 1472 1473 return sharedSecret; 1474} 1475 1476 1477static CFStringRef 1478copyUserXAuthID(CFDictionaryRef config, SCUserPreferencesRef userPreferences) 1479{ 1480 CFMutableStringRef xauth_id = NULL; 1481 1482 if (config != NULL) { 1483 CFStringRef encryption; 1484 1485 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPasswordEncryption); 1486 if (isA_CFString(encryption) && 1487 CFEqual(encryption, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) { 1488 xauth_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPassword); 1489 if (xauth_id != NULL) { 1490 CFRetain(xauth_id); 1491 } 1492 } 1493 } 1494 1495 if (xauth_id == NULL) { 1496 CFStringRef unique_id; 1497 1498 unique_id = getUserPasswordID(config, userPreferences); 1499 xauth_id = CFStringCreateMutableCopy(NULL, 0, unique_id); 1500 CFStringAppend(xauth_id, CFSTR(".XAUTH")); 1501 } 1502 1503 return xauth_id; 1504} 1505 1506 1507static Boolean 1508checkUserPreferencesPassword(SCUserPreferencesRef userPreferences, 1509 SCNetworkInterfaceRef interface, 1510 SCNetworkInterfacePasswordType passwordType) 1511{ 1512 if (!isA_SCUserPreferences(userPreferences)) { 1513 _SCErrorSet(kSCStatusInvalidArgument); 1514 return FALSE; 1515 } 1516 1517 if (!isA_SCNetworkInterface(interface)) { 1518 _SCErrorSet(kSCStatusInvalidArgument); 1519 return FALSE; 1520 } 1521 1522 switch (passwordType) { 1523 case kSCNetworkInterfacePasswordTypePPP : { 1524 CFStringRef interfaceType; 1525 1526 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1527 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 1528 _SCErrorSet(kSCStatusInvalidArgument); 1529 return FALSE; 1530 } 1531 break; 1532 } 1533 1534 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 1535 CFStringRef interfaceType; 1536 1537 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1538 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { 1539 _SCErrorSet(kSCStatusInvalidArgument); 1540 return FALSE; 1541 } 1542 1543 interface = SCNetworkInterfaceGetInterface(interface); 1544 if (interface == NULL) { 1545 _SCErrorSet(kSCStatusInvalidArgument); 1546 return FALSE; 1547 } 1548 1549 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1550 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) { 1551 _SCErrorSet(kSCStatusInvalidArgument); 1552 return FALSE; 1553 } 1554 break; 1555 } 1556 1557 case kSCNetworkInterfacePasswordTypeEAPOL : { 1558 _SCErrorSet(kSCStatusInvalidArgument); 1559 return FALSE; 1560 } 1561 1562 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 1563 CFStringRef interfaceType; 1564 1565 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1566 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) { 1567 _SCErrorSet(kSCStatusInvalidArgument); 1568 return FALSE; 1569 } 1570 break; 1571 } 1572 1573 case kSCNetworkInterfacePasswordTypeVPN : { 1574 CFStringRef interfaceType; 1575 1576 interfaceType = SCNetworkInterfaceGetInterfaceType(interface); 1577 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { 1578 _SCErrorSet(kSCStatusInvalidArgument); 1579 return FALSE; 1580 } 1581 break; 1582 } 1583 1584 default : 1585 break; 1586 } 1587 1588 return TRUE; 1589} 1590 1591 1592Boolean 1593SCUserPreferencesCheckInterfacePassword(SCUserPreferencesRef userPreferences, 1594 SCNetworkInterfaceRef interface, 1595 SCNetworkInterfacePasswordType passwordType) 1596{ 1597 Boolean exists = FALSE; 1598 1599 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) { 1600 return FALSE; 1601 } 1602 1603 switch (passwordType) { 1604 case kSCNetworkInterfacePasswordTypePPP : { 1605 CFDictionaryRef config; 1606 CFStringRef unique_id; 1607 1608 // get configuration 1609 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1610 1611 // get userPreferences ID 1612 unique_id = getUserPasswordID(config, userPreferences); 1613 1614 // check 1615 exists = __extract_password(NULL, 1616 config, 1617 kSCPropNetPPPAuthPassword, 1618 kSCPropNetPPPAuthPasswordEncryption, 1619 kSCValNetPPPAuthPasswordEncryptionKeychain, 1620 unique_id, 1621 NULL); 1622 1623 if (config != NULL) CFRelease(config); 1624 break; 1625 } 1626 1627 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 1628 CFDictionaryRef config; 1629 CFStringRef shared_id; 1630 1631 // get configuration 1632 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences, 1633 interface, 1634 kSCEntNetIPSec); 1635 1636 // get sharedSecret ID 1637 shared_id = copyUserSharedSecretID(config, userPreferences); 1638 1639 // check 1640 exists = __extract_password(NULL, 1641 config, 1642 kSCPropNetIPSecSharedSecret, 1643 kSCPropNetIPSecSharedSecretEncryption, 1644 kSCValNetIPSecSharedSecretEncryptionKeychain, 1645 shared_id, 1646 NULL); 1647 1648 if (config != NULL) CFRelease(config); 1649 CFRelease(shared_id); 1650 break; 1651 } 1652 1653 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 1654 CFDictionaryRef config; 1655 CFStringRef xauth_id; 1656 1657 // get configuration 1658 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1659 1660 // get XAuth ID 1661 xauth_id = copyUserXAuthID(config, userPreferences); 1662 1663 // check 1664 exists = __extract_password(NULL, 1665 config, 1666 kSCPropNetIPSecXAuthPassword, 1667 kSCPropNetIPSecXAuthPasswordEncryption, 1668 kSCValNetIPSecXAuthPasswordEncryptionKeychain, 1669 xauth_id, 1670 NULL); 1671 1672 if (config != NULL) CFRelease(config); 1673 CFRelease(xauth_id); 1674 break; 1675 } 1676 1677 case kSCNetworkInterfacePasswordTypeVPN : { 1678 CFDictionaryRef config; 1679 CFStringRef unique_id; 1680 1681 // get configuration 1682 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1683 1684 // get userPreferences ID 1685 unique_id = getUserPasswordID(config, userPreferences); 1686 1687 // check 1688 exists = __extract_password(NULL, 1689 config, 1690 kSCPropNetVPNAuthPassword, 1691 kSCPropNetVPNAuthPasswordEncryption, 1692 kSCValNetVPNAuthPasswordEncryptionKeychain, 1693 unique_id, 1694 NULL); 1695 1696 if (config != NULL) CFRelease(config); 1697 break; 1698 } 1699 1700 default : 1701 _SCErrorSet(kSCStatusInvalidArgument); 1702 return FALSE; 1703 } 1704 1705 return exists; 1706} 1707 1708 1709CFDataRef 1710SCUserPreferencesCopyInterfacePassword(SCUserPreferencesRef userPreferences, 1711 SCNetworkInterfaceRef interface, 1712 SCNetworkInterfacePasswordType passwordType) 1713{ 1714 CFDataRef password = NULL; 1715 1716 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) { 1717 return FALSE; 1718 } 1719 1720 switch (passwordType) { 1721 case kSCNetworkInterfacePasswordTypePPP : { 1722 CFDictionaryRef config; 1723 CFStringRef unique_id; 1724 1725 // get configuration 1726 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1727 1728 // get userPreferences ID 1729 unique_id = getUserPasswordID(config, userPreferences); 1730 1731 // extract 1732 (void) __extract_password(NULL, 1733 config, 1734 kSCPropNetPPPAuthPassword, 1735 kSCPropNetPPPAuthPasswordEncryption, 1736 kSCValNetPPPAuthPasswordEncryptionKeychain, 1737 unique_id, 1738 &password); 1739 1740 if (config != NULL) CFRelease(config); 1741 break; 1742 } 1743 1744 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 1745 CFDictionaryRef config; 1746 CFStringRef shared_id; 1747 1748 // get configuration 1749 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences, 1750 interface, 1751 kSCEntNetIPSec); 1752 1753 // get sharedSecret ID 1754 shared_id = copyUserSharedSecretID(config, userPreferences); 1755 1756 // extract 1757 (void) __extract_password(NULL, 1758 config, 1759 kSCPropNetIPSecSharedSecret, 1760 kSCPropNetIPSecSharedSecretEncryption, 1761 kSCValNetIPSecSharedSecretEncryptionKeychain, 1762 shared_id, 1763 &password); 1764 1765 if (config != NULL) CFRelease(config); 1766 CFRelease(shared_id); 1767 break; 1768 } 1769 1770 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 1771 CFDictionaryRef config; 1772 CFStringRef xauth_id; 1773 1774 // get configuration 1775 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1776 1777 // get XAuth ID 1778 xauth_id = copyUserXAuthID(config, userPreferences); 1779 1780 // extract 1781 (void) __extract_password(NULL, 1782 config, 1783 kSCPropNetIPSecXAuthPassword, 1784 kSCPropNetIPSecXAuthPasswordEncryption, 1785 kSCValNetIPSecXAuthPasswordEncryptionKeychain, 1786 xauth_id, 1787 &password); 1788 1789 if (config != NULL) CFRelease(config); 1790 CFRelease(xauth_id); 1791 break; 1792 } 1793 1794 case kSCNetworkInterfacePasswordTypeVPN : { 1795 CFDictionaryRef config; 1796 CFStringRef unique_id; 1797 1798 // get configuration 1799 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1800 1801 // get userPreferences ID 1802 unique_id = getUserPasswordID(config, userPreferences); 1803 1804 // extract 1805 (void) __extract_password(NULL, 1806 config, 1807 kSCPropNetVPNAuthPassword, 1808 kSCPropNetVPNAuthPasswordEncryption, 1809 kSCValNetVPNAuthPasswordEncryptionKeychain, 1810 unique_id, 1811 &password); 1812 1813 if (config != NULL) CFRelease(config); 1814 break; 1815 } 1816 1817 default : 1818 _SCErrorSet(kSCStatusInvalidArgument); 1819 return NULL; 1820 } 1821 1822 return password; 1823} 1824 1825 1826Boolean 1827SCUserPreferencesRemoveInterfacePassword(SCUserPreferencesRef userPreferences, 1828 SCNetworkInterfaceRef interface, 1829 SCNetworkInterfacePasswordType passwordType) 1830{ 1831 Boolean ok = FALSE; 1832 1833 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) { 1834 return FALSE; 1835 } 1836 1837 switch (passwordType) { 1838 case kSCNetworkInterfacePasswordTypePPP : { 1839 CFDictionaryRef config; 1840 CFDictionaryRef newConfig = NULL; 1841 CFStringRef unique_id; 1842 1843 // get configuration 1844 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1845 1846 // get userPreferences ID 1847 unique_id = getUserPasswordID(config, userPreferences); 1848 1849 // remove password 1850 ok = __remove_password(NULL, 1851 config, 1852 kSCPropNetPPPAuthPassword, 1853 kSCPropNetPPPAuthPasswordEncryption, 1854 kSCValNetPPPAuthPasswordEncryptionKeychain, 1855 unique_id, 1856 &newConfig); 1857 if (ok) { 1858 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig); 1859 if (newConfig != NULL) CFRelease(newConfig); 1860 } 1861 1862 if (config != NULL) CFRelease(config); 1863 break; 1864 } 1865 1866 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 1867 CFDictionaryRef config; 1868 CFDictionaryRef newConfig = NULL; 1869 CFStringRef shared_id; 1870 1871 // get configuration 1872 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences, 1873 interface, 1874 kSCEntNetIPSec); 1875 1876 // get sharedSecret ID 1877 shared_id = copyUserSharedSecretID(config, userPreferences); 1878 1879 // remove password 1880 ok = __remove_password(NULL, 1881 config, 1882 kSCPropNetIPSecSharedSecret, 1883 kSCPropNetIPSecSharedSecretEncryption, 1884 kSCValNetIPSecSharedSecretEncryptionKeychain, 1885 shared_id, 1886 &newConfig); 1887 if (ok) { 1888 ok = SCUserPreferencesSetExtendedInterfaceConfiguration(userPreferences, 1889 interface, 1890 kSCEntNetIPSec, 1891 newConfig); 1892 if (newConfig != NULL) CFRelease(newConfig); 1893 } 1894 1895 if (config != NULL) CFRelease(config); 1896 CFRelease(shared_id); 1897 break; 1898 } 1899 1900 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 1901 CFDictionaryRef config; 1902 CFDictionaryRef newConfig = NULL; 1903 CFStringRef xauth_id; 1904 1905 // get configuration 1906 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1907 1908 // get XAuth ID 1909 xauth_id = copyUserXAuthID(config, userPreferences); 1910 1911 // remove password 1912 ok = __remove_password(NULL, 1913 config, 1914 kSCPropNetIPSecXAuthPassword, 1915 kSCPropNetIPSecXAuthPasswordEncryption, 1916 kSCValNetIPSecXAuthPasswordEncryptionKeychain, 1917 xauth_id, 1918 &newConfig); 1919 if (ok) { 1920 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig); 1921 if (newConfig != NULL) CFRelease(newConfig); 1922 } 1923 1924 if (config != NULL) CFRelease(config); 1925 CFRelease(xauth_id); 1926 break; 1927 } 1928 1929 case kSCNetworkInterfacePasswordTypeVPN : { 1930 CFDictionaryRef config; 1931 CFDictionaryRef newConfig = NULL; 1932 CFStringRef unique_id; 1933 1934 // get configuration 1935 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1936 1937 // get userPreferences ID 1938 unique_id = getUserPasswordID(config, userPreferences); 1939 1940 // remove password 1941 ok = __remove_password(NULL, 1942 config, 1943 kSCPropNetVPNAuthPassword, 1944 kSCPropNetVPNAuthPasswordEncryption, 1945 kSCValNetVPNAuthPasswordEncryptionKeychain, 1946 unique_id, 1947 &newConfig); 1948 if (ok) { 1949 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig); 1950 if (newConfig != NULL) CFRelease(newConfig); 1951 } 1952 1953 if (config != NULL) CFRelease(config); 1954 break; 1955 } 1956 1957 default : 1958 _SCErrorSet(kSCStatusInvalidArgument); 1959 return FALSE; 1960 } 1961 1962 return ok; 1963} 1964 1965 1966Boolean 1967SCUserPreferencesSetInterfacePassword(SCUserPreferencesRef userPreferences, 1968 SCNetworkInterfaceRef interface, 1969 SCNetworkInterfacePasswordType passwordType, 1970 CFDataRef password, 1971 CFDictionaryRef options) 1972{ 1973 CFStringRef account = NULL; 1974 CFBundleRef bundle; 1975 CFDictionaryRef config; 1976 CFStringRef description = NULL; 1977 CFStringRef label = NULL; 1978 Boolean ok = FALSE; 1979 1980 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) { 1981 return FALSE; 1982 } 1983 1984 bundle = _SC_CFBundleGet(); 1985 1986 switch (passwordType) { 1987 case kSCNetworkInterfacePasswordTypePPP : { 1988 CFStringRef unique_id; 1989 1990 // get configuration 1991 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 1992 1993 // get userPreferences ID 1994 unique_id = getUserPasswordID(config, userPreferences); 1995 1996 // User prefs auth name --> keychain "Account" 1997 if (config != NULL) { 1998 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName); 1999 } 2000 2001 // User prefs "name" --> keychain "Name" 2002 label = SCUserPreferencesCopyName(userPreferences); 2003 2004 // "PPP Password" --> keychain "Kind" 2005 if (bundle != NULL) { 2006 description = CFBundleCopyLocalizedString(bundle, 2007 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"), 2008 CFSTR("PPP Password"), 2009 NULL); 2010 } 2011 2012 // store password 2013 ok = _SCSecKeychainPasswordItemSet(NULL, 2014 unique_id, 2015 (label != NULL) ? label : CFSTR("Network Connection"), 2016 (description != NULL) ? description : CFSTR("PPP Password"), 2017 account, 2018 password, 2019 options); 2020 if (ok) { 2021 CFMutableDictionaryRef newConfig; 2022 2023 if (config != NULL) { 2024 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 2025 } else { 2026 newConfig = CFDictionaryCreateMutable(NULL, 2027 0, 2028 &kCFTypeDictionaryKeyCallBacks, 2029 &kCFTypeDictionaryValueCallBacks); 2030 } 2031 CFDictionarySetValue(newConfig, 2032 kSCPropNetPPPAuthPassword, 2033 unique_id); 2034 CFDictionarySetValue(newConfig, 2035 kSCPropNetPPPAuthPasswordEncryption, 2036 kSCValNetPPPAuthPasswordEncryptionKeychain); 2037 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig); 2038 CFRelease(newConfig); 2039 } 2040 2041 if (config != NULL) CFRelease(config); 2042 if (description != NULL) CFRelease(description); 2043 if (label != NULL) CFRelease(label); 2044 break; 2045 } 2046 2047 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : { 2048 CFStringRef shared_id; 2049 2050 // get configuration 2051 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences, 2052 interface, 2053 kSCEntNetIPSec); 2054 2055 // get sharedSecret ID 2056 shared_id = copyUserSharedSecretID(config, userPreferences); 2057 2058 // User prefs "name" --> keychain "Name" 2059 label = SCUserPreferencesCopyName(userPreferences); 2060 2061 // "IPSec Shared Secret" --> keychain "Kind" 2062 if (bundle != NULL) { 2063 description = CFBundleCopyLocalizedString(bundle, 2064 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"), 2065 CFSTR("IPSec Shared Secret"), 2066 NULL); 2067 } 2068 2069 // set password 2070 ok = _SCSecKeychainPasswordItemSet(NULL, 2071 shared_id, 2072 (label != NULL) ? label : CFSTR("Network Connection"), 2073 (description != NULL) ? description : CFSTR("IPSec Shared Secret"), 2074 NULL, 2075 password, 2076 options); 2077 if (ok) { 2078 CFMutableDictionaryRef newConfig = NULL; 2079 2080 if (config != NULL) { 2081 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 2082 } else { 2083 newConfig = CFDictionaryCreateMutable(NULL, 2084 0, 2085 &kCFTypeDictionaryKeyCallBacks, 2086 &kCFTypeDictionaryValueCallBacks); 2087 } 2088 CFDictionarySetValue(newConfig, 2089 kSCPropNetIPSecSharedSecret, 2090 shared_id); 2091 CFDictionarySetValue(newConfig, 2092 kSCPropNetIPSecSharedSecretEncryption, 2093 kSCValNetIPSecSharedSecretEncryptionKeychain); 2094 ok = SCUserPreferencesSetExtendedInterfaceConfiguration(userPreferences, 2095 interface, 2096 kSCEntNetIPSec, 2097 newConfig); 2098 CFRelease(newConfig); 2099 } 2100 2101 if (config != NULL) CFRelease(config); 2102 if (description != NULL) CFRelease(description); 2103 if (label != NULL) CFRelease(label); 2104 CFRelease(shared_id); 2105 break; 2106 } 2107 2108 case kSCNetworkInterfacePasswordTypeIPSecXAuth : { 2109 CFStringRef xauth_id; 2110 2111 // get configuration 2112 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 2113 2114 // get XAuth ID 2115 xauth_id = copyUserXAuthID(config, userPreferences); 2116 2117 // User prefs XAuth name --> keychain "Account" 2118 if (config != NULL) { 2119 account = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthName); 2120 } 2121 2122 // User prefs "name" --> keychain "Name" 2123 label = SCUserPreferencesCopyName(userPreferences); 2124 2125 // "IPSec XAuth Password" --> keychain "Kind" 2126 if (bundle != NULL) { 2127 description = CFBundleCopyLocalizedString(bundle, 2128 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"), 2129 CFSTR("IPSec XAuth Password"), 2130 NULL); 2131 } 2132 2133 // store password 2134 ok = _SCSecKeychainPasswordItemSet(NULL, 2135 xauth_id, 2136 (label != NULL) ? label : CFSTR("Network Connection"), 2137 (description != NULL) ? description : CFSTR("IPSec XAuth Password"), 2138 account, 2139 password, 2140 options); 2141 if (ok) { 2142 CFMutableDictionaryRef newConfig; 2143 2144 if (config != NULL) { 2145 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 2146 } else { 2147 newConfig = CFDictionaryCreateMutable(NULL, 2148 0, 2149 &kCFTypeDictionaryKeyCallBacks, 2150 &kCFTypeDictionaryValueCallBacks); 2151 } 2152 CFDictionarySetValue(newConfig, 2153 kSCPropNetIPSecXAuthPassword, 2154 xauth_id); 2155 CFDictionarySetValue(newConfig, 2156 kSCPropNetIPSecXAuthPasswordEncryption, 2157 kSCValNetIPSecXAuthPasswordEncryptionKeychain); 2158 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig); 2159 CFRelease(newConfig); 2160 } 2161 2162 if (config != NULL) CFRelease(config); 2163 if (description != NULL) CFRelease(description); 2164 if (label != NULL) CFRelease(label); 2165 CFRelease(xauth_id); 2166 break; 2167 } 2168 2169 case kSCNetworkInterfacePasswordTypeVPN : { 2170 CFStringRef unique_id; 2171 2172 // get configuration 2173 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface); 2174 2175 // get userPreferences ID 2176 unique_id = getUserPasswordID(config, userPreferences); 2177 2178 // User prefs auth name --> keychain "Account" 2179 if (config != NULL) { 2180 account = CFDictionaryGetValue(config, kSCPropNetVPNAuthName); 2181 } 2182 2183 // User prefs "name" --> keychain "Name" 2184 label = SCUserPreferencesCopyName(userPreferences); 2185 2186 // "VPN Password" --> keychain "Kind" 2187 if (bundle != NULL) { 2188 description = CFBundleCopyLocalizedString(bundle, 2189 CFSTR("KEYCHAIN_KIND_VPN_PASSWORD"), 2190 CFSTR("VPN Password"), 2191 NULL); 2192 } 2193 2194 // store password 2195 ok = _SCSecKeychainPasswordItemSet(NULL, 2196 unique_id, 2197 (label != NULL) ? label : CFSTR("Network Connection"), 2198 (description != NULL) ? description : CFSTR("VPN Password"), 2199 account, 2200 password, 2201 options); 2202 if (ok) { 2203 CFMutableDictionaryRef newConfig; 2204 2205 if (config != NULL) { 2206 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); 2207 } else { 2208 newConfig = CFDictionaryCreateMutable(NULL, 2209 0, 2210 &kCFTypeDictionaryKeyCallBacks, 2211 &kCFTypeDictionaryValueCallBacks); 2212 } 2213 assert(newConfig != NULL); 2214 CFDictionarySetValue(newConfig, 2215 kSCPropNetVPNAuthPassword, 2216 unique_id); 2217 CFDictionarySetValue(newConfig, 2218 kSCPropNetVPNAuthPasswordEncryption, 2219 kSCValNetVPNAuthPasswordEncryptionKeychain); 2220 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig); 2221 CFRelease(newConfig); 2222 } 2223 2224 if (config != NULL) CFRelease(config); 2225 if (description != NULL) CFRelease(description); 2226 if (label != NULL) CFRelease(label); 2227 break; 2228 } 2229 2230 default : 2231 _SCErrorSet(kSCStatusInvalidArgument); 2232 return FALSE; 2233 } 2234 2235 return ok; 2236}