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