]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkConnectionPrivate.c
configd-453.16.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkConnectionPrivate.c
1 /*
2 * Copyright (c) 2006-2011 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 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
440 static __inline__ Boolean
441 isMatchingPrefsID(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
456 CFTypeID
457 SCUserPreferencesGetTypeID(void)
458 {
459 pthread_once(&initialized, __SCUserPreferencesInitialize); /* initialize runtime */
460 return __kSCUserPreferencesTypeID;
461 }
462
463
464 CFStringRef
465 SCUserPreferencesGetUniqueID(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
478 Boolean
479 SCUserPreferencesIsForced(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
492 static CFDictionaryRef
493 removeCallout(CFStringRef serviceID,
494 CFDictionaryRef current,
495 void *context1,
496 void *context2,
497 void *context3)
498 {
499 CFStringRef matchID = (CFStringRef)context1;
500
501 if (current == NULL) {
502 // we have nothing to "add"
503 return NULL;
504 }
505
506 if (isMatchingPrefsID(current, matchID)) {
507 // if we match, don't add (i.e. remove)
508 return NULL;
509 }
510
511 return CFRetain(current);
512 }
513
514
515 Boolean
516 SCUserPreferencesRemove(SCUserPreferencesRef userPreferences)
517 {
518 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
519
520 if (!isA_SCUserPreferences(userPreferences)) {
521 _SCErrorSet(kSCStatusInvalidArgument);
522 return FALSE;
523 }
524
525 return processPreferences(userPrivate->serviceID,
526 removeCallout,
527 (void *)userPrivate->prefsID,
528 NULL,
529 NULL);
530 }
531
532
533 static CF_RETURNS_RETAINED CFDictionaryRef
534 setCurrentCallout(CFStringRef serviceID,
535 CFDictionaryRef current,
536 void *context1,
537 void *context2,
538 void *context3)
539 {
540 CFStringRef matchID = (CFStringRef)context1;
541 CFMutableDictionaryRef newDict;
542
543 if (current == NULL) {
544 // we have nothing to "add"
545 return NULL;
546 }
547
548 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current);
549
550 // remove "default" flag
551 CFDictionaryRemoveValue(newDict, USER_PREFERENCES_DEFAULT);
552
553 if (isMatchingPrefsID(current, matchID)) {
554 // if we match, set "default" flag
555 CFDictionarySetValue(newDict, USER_PREFERENCES_DEFAULT, kCFBooleanTrue);
556 }
557
558 return newDict;
559 }
560
561
562 Boolean
563 SCUserPreferencesSetCurrent(SCUserPreferencesRef userPreferences)
564 {
565 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
566
567 if (!isA_SCUserPreferences(userPreferences)) {
568 _SCErrorSet(kSCStatusInvalidArgument);
569 return FALSE;
570 }
571
572 return processPreferences(userPrivate->serviceID,
573 setCurrentCallout,
574 (void *)userPrivate->prefsID,
575 NULL,
576 NULL);
577 }
578
579
580 static CFDictionaryRef
581 copyNameCallout(CFStringRef serviceID,
582 CFDictionaryRef current,
583 void *context1,
584 void *context2,
585 void *context3)
586 {
587 CFStringRef matchID = (CFStringRef)context1;
588 CFStringRef *name = (CFStringRef *)context3;
589
590 if (current == NULL) {
591 // we have nothing to "add"
592 return NULL;
593 }
594
595 if (isMatchingPrefsID(current, matchID)) {
596 *name = CFDictionaryGetValue(current, kSCPropUserDefinedName);
597
598 // for backwards compatibility, we also check for the name in the PPP entity
599 if (*name == NULL) {
600 CFDictionaryRef ppp;
601
602 ppp = CFDictionaryGetValue(current, kSCEntNetPPP);
603 if (isA_CFDictionary(ppp)) {
604 *name = CFDictionaryGetValue(ppp, kSCPropUserDefinedName);
605 }
606 }
607
608 *name = isA_CFString(*name);
609 if (*name != NULL) {
610 CFRetain(*name);
611 }
612 }
613
614 return CFRetain(current);
615 }
616
617
618 CFStringRef
619 SCUserPreferencesCopyName(SCUserPreferencesRef userPreferences)
620 {
621 CFStringRef name = NULL;
622 Boolean ok;
623 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
624
625 if (!isA_SCUserPreferences(userPreferences)) {
626 _SCErrorSet(kSCStatusInvalidArgument);
627 return FALSE;
628 }
629
630 // find SCUserPreferences and copy name
631 ok = processPreferences(userPrivate->serviceID,
632 copyNameCallout,
633 (void *)userPrivate->prefsID,
634 NULL,
635 (void *)&name);
636 if (!ok) {
637 if (name != NULL) {
638 CFRelease(name);
639 name = NULL;
640 }
641 }
642
643 return name;
644 }
645
646
647 static CF_RETURNS_RETAINED CFDictionaryRef
648 setNameCallout(CFStringRef serviceID,
649 CFDictionaryRef current,
650 void *context1,
651 void *context2,
652 void *context3)
653 {
654 CFStringRef matchID = (CFStringRef)context1;
655 CFMutableDictionaryRef newDict;
656 CFStringRef newName = (CFStringRef)context2;
657
658 if (current == NULL) {
659 // we have nothing to "add"
660 return NULL;
661 }
662
663 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current);
664
665 if (isMatchingPrefsID(current, matchID)) {
666 CFDictionaryRef pppEntity;
667
668 // set the name
669 if (newName != NULL) {
670 CFDictionarySetValue(newDict, kSCPropUserDefinedName, newName);
671 } else {
672 CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName);
673 }
674
675 // for backwards compatibility, we also set the name in the PPP entity
676 pppEntity = CFDictionaryGetValue(newDict, kSCEntNetPPP);
677 if (isA_CFDictionary(pppEntity)) {
678 CFMutableDictionaryRef newPPPEntity;
679
680 newPPPEntity = CFDictionaryCreateMutableCopy(NULL, 0, pppEntity);
681 if (newName != NULL) {
682 CFDictionarySetValue(newPPPEntity, kSCPropUserDefinedName, newName);
683 } else {
684 CFDictionaryRemoveValue(newPPPEntity, kSCPropUserDefinedName);
685 }
686 CFDictionarySetValue(newDict, kSCEntNetPPP, newPPPEntity);
687 CFRelease(newPPPEntity);
688 }
689 }
690
691 return newDict;
692 }
693
694
695 Boolean
696 SCUserPreferencesSetName(SCUserPreferencesRef userPreferences, CFStringRef newName)
697 {
698 Boolean ok;
699 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
700
701 if (!isA_SCUserPreferences(userPreferences)) {
702 _SCErrorSet(kSCStatusInvalidArgument);
703 return FALSE;
704 }
705
706 if ((newName != NULL) && !isA_CFString(newName)) {
707 _SCErrorSet(kSCStatusInvalidArgument);
708 return FALSE;
709 }
710
711 // find SCUserPreferences and set name
712 ok = processPreferences(userPrivate->serviceID,
713 setNameCallout,
714 (void *)userPrivate->prefsID,
715 (void *)newName,
716 NULL);
717
718 return ok;
719 }
720
721
722 static CFDictionaryRef
723 copyInterfaceConfigurationCallout(CFStringRef serviceID,
724 CFDictionaryRef current,
725 void *context1,
726 void *context2,
727 void *context3)
728 {
729 CFDictionaryRef *dict = (CFDictionaryRef *)context3;
730 CFStringRef interfaceType = (CFStringRef)context2;
731 CFStringRef matchID = (CFStringRef)context1;
732
733 if (current == NULL) {
734 // we have nothing to "add"
735 return NULL;
736 }
737
738 if (isMatchingPrefsID(current, matchID)) {
739 *dict = CFDictionaryGetValue(current, interfaceType);
740 *dict = isA_CFDictionary(*dict);
741 if (*dict != NULL) {
742 CFRetain(*dict);
743 }
744 }
745
746 return CFRetain(current);
747 }
748
749
750 CFDictionaryRef
751 SCUserPreferencesCopyInterfaceConfiguration(SCUserPreferencesRef userPreferences,
752 SCNetworkInterfaceRef interface)
753 {
754 CFStringRef defaultType;
755 CFDictionaryRef entity = NULL;
756 Boolean ok;
757 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
758
759 if (!isA_SCUserPreferences(userPreferences)) {
760 _SCErrorSet(kSCStatusInvalidArgument);
761 return NULL;
762 }
763
764 if (!isA_SCNetworkInterface(interface)) {
765 _SCErrorSet(kSCStatusInvalidArgument);
766 return NULL;
767 }
768
769 // get InterfaceType
770 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
771 if (defaultType == NULL) {
772 _SCErrorSet(kSCStatusInvalidArgument);
773 return NULL;
774 }
775
776 // find SCUserPreferences and copy interface entity
777 ok = processPreferences(userPrivate->serviceID,
778 copyInterfaceConfigurationCallout,
779 (void *)userPrivate->prefsID,
780 (void *)defaultType,
781 (void *)&entity);
782 if (!ok) {
783 if (entity != NULL) {
784 CFRelease(entity);
785 entity = NULL;
786 }
787 }
788
789 return entity;
790 }
791
792
793 static CF_RETURNS_RETAINED CFDictionaryRef
794 setInterfaceConfigurationCallout(CFStringRef serviceID,
795 CFDictionaryRef current,
796 void *context1,
797 void *context2,
798 void *context3)
799 {
800 CFStringRef interfaceType = (CFStringRef)context2;
801 CFStringRef matchID = (CFStringRef)context1;
802 CFMutableDictionaryRef newDict;
803 CFDictionaryRef newOptions = (CFDictionaryRef)context3;
804
805 if (current == NULL) {
806 // we have nothing to "add"
807 return NULL;
808 }
809
810 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current);
811
812 if (isMatchingPrefsID(current, matchID)) {
813 if (newOptions != NULL) {
814 CFDictionarySetValue(newDict, interfaceType, newOptions);
815
816 // for backwards compatibility, we want to ensure that
817 // the name is set in both the top level and in the PPP
818 // entity.
819 if (CFEqual(interfaceType, kSCEntNetPPP)) {
820 CFStringRef name;
821
822 name = CFDictionaryGetValue(newOptions, kSCPropUserDefinedName);
823 if (name != NULL) {
824 // if name was passed in newOptions, push up
825 CFDictionarySetValue(newDict, kSCPropUserDefinedName, name);
826 } else {
827 name = CFDictionaryGetValue(newDict, kSCPropUserDefinedName);
828 if (name != NULL) {
829 CFMutableDictionaryRef newPPPEntity;
830
831 // if name in parent, push into entity
832 newPPPEntity = CFDictionaryCreateMutableCopy(NULL, 0, newOptions);
833 CFDictionarySetValue(newPPPEntity, kSCPropUserDefinedName, name);
834 CFDictionarySetValue(newDict, interfaceType, newPPPEntity);
835 CFRelease(newPPPEntity);
836 }
837 }
838 }
839 } else {
840 CFDictionaryRemoveValue(newDict, interfaceType);
841 }
842 }
843
844 return newDict;
845 }
846
847
848 Boolean
849 SCUserPreferencesSetInterfaceConfiguration(SCUserPreferencesRef userPreferences,
850 SCNetworkInterfaceRef interface,
851 CFDictionaryRef newOptions)
852 {
853 CFStringRef defaultType;
854 Boolean ok;
855 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
856
857 if (!isA_SCUserPreferences(userPreferences)) {
858 _SCErrorSet(kSCStatusInvalidArgument);
859 return FALSE;
860 }
861
862 if (!isA_SCNetworkInterface(interface)) {
863 _SCErrorSet(kSCStatusInvalidArgument);
864 return FALSE;
865 }
866
867 // get InterfaceType
868 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
869 if (defaultType == NULL) {
870 _SCErrorSet(kSCStatusInvalidArgument);
871 return FALSE;
872 }
873
874 // set new interface entity for SCUserPreferences
875 ok = processPreferences(userPrivate->serviceID,
876 setInterfaceConfigurationCallout,
877 (void *)userPrivate->prefsID,
878 (void *)defaultType,
879 (void *)newOptions);
880
881 return ok;
882 }
883
884
885 CFDictionaryRef
886 SCUserPreferencesCopyExtendedInterfaceConfiguration(SCUserPreferencesRef userPreferences,
887 SCNetworkInterfaceRef interface,
888 CFStringRef extendedType)
889 {
890 CFDictionaryRef entity = NULL;
891 Boolean ok;
892 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
893
894 if (!isA_SCUserPreferences(userPreferences)) {
895 _SCErrorSet(kSCStatusInvalidArgument);
896 return NULL;
897 }
898
899 if (!isA_SCNetworkInterface(interface)) {
900 _SCErrorSet(kSCStatusInvalidArgument);
901 return NULL;
902 }
903
904 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, FALSE)) {
905 _SCErrorSet(kSCStatusInvalidArgument);
906 return NULL;
907 }
908
909 // find SCUserPreferences and copy interface entity
910 ok = processPreferences(userPrivate->serviceID,
911 copyInterfaceConfigurationCallout,
912 (void *)userPrivate->prefsID,
913 (void *)extendedType,
914 (void *)&entity);
915 if (!ok) {
916 if (entity != NULL) {
917 CFRelease(entity);
918 entity = NULL;
919 }
920 }
921
922 return entity;
923 }
924
925
926 Boolean
927 SCUserPreferencesSetExtendedInterfaceConfiguration(SCUserPreferencesRef userPreferences,
928 SCNetworkInterfaceRef interface,
929 CFStringRef extendedType,
930 CFDictionaryRef newOptions)
931 {
932 Boolean ok;
933 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
934
935 if (!isA_SCUserPreferences(userPreferences)) {
936 _SCErrorSet(kSCStatusInvalidArgument);
937 return FALSE;
938 }
939
940 if (!isA_SCNetworkInterface(interface)) {
941 _SCErrorSet(kSCStatusInvalidArgument);
942 return FALSE;
943 }
944
945 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, FALSE)) {
946 _SCErrorSet(kSCStatusInvalidArgument);
947 return FALSE;
948 }
949
950 // set new interface entity for SCUserPreferences
951 ok = processPreferences(userPrivate->serviceID,
952 setInterfaceConfigurationCallout,
953 (void *)userPrivate->prefsID,
954 (void *)extendedType,
955 (void *)newOptions);
956
957 return ok;
958 }
959
960
961 #pragma mark -
962 #pragma mark SCNetworkConnection + SCUserPreferences SPIs
963
964
965 static CFDictionaryRef
966 copyAllCallout(CFStringRef serviceID,
967 CFDictionaryRef current,
968 void *context1,
969 void *context2,
970 void *context3)
971 {
972 CFMutableArrayRef *prefs = (CFMutableArrayRef *)context3;
973 CFStringRef prefsID;
974 SCUserPreferencesPrivateRef userPrivate;
975
976 if (current == NULL) {
977 // we have nothing to "add"
978 return NULL;
979 }
980
981 prefsID = CFDictionaryGetValue(current, USER_PREFERENCES_ID);
982 if (!isA_CFString(prefsID)) {
983 // if no unique ID
984 goto done;
985 }
986
987 userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, prefsID);
988 if (userPrivate != NULL) {
989 if (*prefs == NULL) {
990 *prefs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
991 }
992 CFArrayAppendValue(*prefs, (SCUserPreferencesRef)userPrivate);
993 CFRelease(userPrivate);
994 }
995
996 done :
997
998 return CFRetain(current);
999 }
1000
1001
1002 CFArrayRef /* of SCUserPreferencesRef's */
1003 SCNetworkConnectionCopyAllUserPreferences(SCNetworkConnectionRef connection)
1004 {
1005 Boolean ok;
1006 CFMutableArrayRef prefs = NULL;
1007 CFStringRef serviceID;
1008
1009 // get serviceID
1010 serviceID = SCNetworkConnectionCopyServiceID(connection);
1011
1012 // collect SCUserPreferences
1013 ok = processPreferences(serviceID,
1014 copyAllCallout,
1015 NULL,
1016 NULL,
1017 (void *)&prefs);
1018 if (!ok) {
1019 if (prefs != NULL) {
1020 CFRelease(prefs);
1021 prefs = NULL;
1022 }
1023 }
1024
1025 CFRelease(serviceID);
1026 return prefs;
1027 }
1028
1029
1030 static CFDictionaryRef
1031 copyCurrentCallout(CFStringRef serviceID,
1032 CFDictionaryRef current,
1033 void *context1,
1034 void *context2,
1035 void *context3)
1036 {
1037 CFBooleanRef isDefault;
1038 CFStringRef prefsID;
1039 SCUserPreferencesPrivateRef *userPrivate = (SCUserPreferencesPrivateRef *)context3;
1040
1041 if (current == NULL) {
1042 // we have nothing to "add"
1043 return NULL;
1044 }
1045
1046 prefsID = CFDictionaryGetValue(current, USER_PREFERENCES_ID);
1047 if (!isA_CFString(prefsID)) {
1048 // if no unique ID
1049 goto done;
1050 }
1051
1052 isDefault = CFDictionaryGetValue(current, USER_PREFERENCES_DEFAULT);
1053 if (!isA_CFBoolean(isDefault) || !CFBooleanGetValue(isDefault)) {
1054 // if not the default configuration
1055 goto done;
1056 }
1057
1058 *userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, prefsID);
1059
1060 done :
1061
1062 return CFRetain(current);
1063 }
1064
1065
1066 SCUserPreferencesRef
1067 SCNetworkConnectionCopyCurrentUserPreferences(SCNetworkConnectionRef connection)
1068 {
1069 SCUserPreferencesRef current = NULL;
1070 Boolean ok;
1071 CFStringRef serviceID;
1072
1073 // get serviceID
1074 serviceID = SCNetworkConnectionCopyServiceID(connection);
1075
1076 // collect SCUserPreferences
1077 ok = processPreferences(serviceID,
1078 copyCurrentCallout,
1079 NULL,
1080 NULL,
1081 (void *)&current);
1082 if (!ok) {
1083 if (current != NULL) {
1084 CFRelease(current);
1085 current = NULL;
1086 }
1087 }
1088
1089 CFRelease(serviceID);
1090 return current;
1091 }
1092
1093
1094 static CFDictionaryRef
1095 createCallout(CFStringRef serviceID,
1096 CFDictionaryRef current,
1097 void *context1,
1098 void *context2,
1099 void *context3)
1100 {
1101 CFMutableDictionaryRef newDict;
1102 CFStringRef newPrefsID = (CFStringRef)context1;
1103
1104 if (current != NULL) {
1105 // don't change existing entries
1106 return CFRetain(current);
1107 }
1108
1109 newDict = CFDictionaryCreateMutable(NULL,
1110 0,
1111 &kCFTypeDictionaryKeyCallBacks,
1112 &kCFTypeDictionaryValueCallBacks);
1113 CFDictionarySetValue(newDict, USER_PREFERENCES_ID, newPrefsID);
1114 return newDict;
1115 }
1116
1117
1118 SCUserPreferencesRef
1119 SCNetworkConnectionCreateUserPreferences(SCNetworkConnectionRef connection)
1120 {
1121 CFStringRef newPrefsID;
1122 CFStringRef serviceID;
1123 SCUserPreferencesPrivateRef userPrivate;
1124 CFUUIDRef uuid;
1125
1126 // get serviceID
1127 serviceID = SCNetworkConnectionCopyServiceID(connection);
1128
1129 // allocate a new user preferences ID
1130 uuid = CFUUIDCreate(NULL);
1131 newPrefsID = CFUUIDCreateString(NULL, uuid);
1132 CFRelease(uuid);
1133
1134 userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, newPrefsID);
1135 if (userPrivate != NULL) {
1136 (void) processPreferences(serviceID,
1137 createCallout,
1138 (void *)newPrefsID,
1139 NULL,
1140 NULL);
1141 }
1142
1143 CFRelease(newPrefsID);
1144 CFRelease(serviceID);
1145 return (SCUserPreferencesRef)userPrivate;
1146 }
1147
1148
1149 static void
1150 update_PPP_entity(SCUserPreferencesRef userPreferences, CFDictionaryRef *userOptions)
1151 {
1152 CFStringRef encryption;
1153 CFDictionaryRef entity;
1154 CFStringRef keychainID;
1155
1156 entity = CFDictionaryGetValue(*userOptions, kSCEntNetPPP);
1157 if (!isA_CFDictionary(entity)) {
1158 return;
1159 }
1160
1161 encryption = CFDictionaryGetValue(entity, kSCPropNetPPPAuthPasswordEncryption);
1162 if (encryption == NULL) {
1163 // provide default encryption method
1164 encryption = kSCValNetPPPAuthPasswordEncryptionKeychain;
1165 }
1166
1167 if (!isA_CFString(encryption) ||
1168 !CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
1169 return;
1170 }
1171
1172 keychainID = CFDictionaryGetValue(entity, kSCPropNetPPPAuthPassword);
1173 if (isA_CFString(keychainID)) {
1174 // if password is keychain ID
1175 } else if (isA_CFData(keychainID) &&
1176 ((CFDataGetLength((CFDataRef)keychainID) % sizeof(UniChar)) == 0)) {
1177 // if inline password
1178 return;
1179 } else {
1180 keychainID = SCUserPreferencesGetUniqueID(userPreferences);
1181 }
1182
1183 if (_SCSecKeychainPasswordItemExists(NULL, keychainID)) {
1184 CFMutableDictionaryRef new_entity;
1185 CFMutableDictionaryRef new_options;
1186
1187 // access PPP password from system keychain
1188 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
1189
1190 CFDictionarySetValue(new_entity,
1191 kSCPropNetPPPAuthPassword,
1192 keychainID);
1193 CFDictionarySetValue(new_entity,
1194 kSCPropNetPPPAuthPasswordEncryption,
1195 kSCValNetPPPAuthPasswordEncryptionKeychain);
1196
1197 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
1198 CFDictionarySetValue(new_options, kSCEntNetPPP, new_entity);
1199 CFRelease(new_entity);
1200
1201 CFRelease(*userOptions);
1202 *userOptions = new_options;
1203 }
1204
1205 return;
1206 }
1207
1208
1209 static void
1210 update_IPSec_entity(SCUserPreferencesRef userPreferences, CFDictionaryRef *userOptions)
1211 {
1212 CFStringRef encryption;
1213 CFDictionaryRef entity;
1214 SecKeychainRef keychain = NULL;
1215 CFStringRef keychainID;
1216 CFStringRef method;
1217 CFDataRef sharedSecret;
1218
1219 entity = CFDictionaryGetValue(*userOptions, kSCEntNetIPSec);
1220 if (!isA_CFDictionary(entity)) {
1221 return;
1222 }
1223
1224 method = CFDictionaryGetValue(entity, kSCPropNetIPSecAuthenticationMethod);
1225 if (!isA_CFString(method) ||
1226 !CFEqual(method, kSCValNetIPSecAuthenticationMethodSharedSecret)) {
1227 return;
1228 }
1229
1230 encryption = CFDictionaryGetValue(entity, kSCPropNetIPSecSharedSecretEncryption);
1231 if (encryption == NULL) {
1232 // provide default encryption method
1233 encryption = kSCValNetIPSecSharedSecretEncryptionKeychain;
1234 }
1235
1236 if (!isA_CFString(encryption) ||
1237 !CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
1238 return;
1239 }
1240
1241 keychainID = CFDictionaryGetValue(entity, kSCPropNetIPSecSharedSecret);
1242 if (isA_CFString(keychainID)) {
1243 // if shared secret is keychain ID
1244 CFRetain(keychainID);
1245 } else if (isA_CFData(keychainID) &&
1246 ((CFDataGetLength((CFDataRef)keychainID) % sizeof(UniChar)) == 0)) {
1247 // if inline shared secret
1248 return;
1249 } else {
1250 CFStringRef unique_id;
1251
1252 unique_id = SCUserPreferencesGetUniqueID(userPreferences);
1253 keychainID = (CFStringRef)CFStringCreateMutableCopy(NULL, 0, unique_id);
1254 CFStringAppend((CFMutableStringRef)keychainID, CFSTR(".SS"));
1255 }
1256
1257 sharedSecret = _SCSecKeychainPasswordItemCopy(NULL, keychainID);
1258 if (sharedSecret != NULL) {
1259 CFMutableDictionaryRef new_entity;
1260 CFMutableDictionaryRef new_options;
1261 CFStringRef password;
1262
1263 // pass SharedSecret from user keychain
1264 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
1265
1266 password = CFStringCreateWithBytes(NULL,
1267 CFDataGetBytePtr(sharedSecret),
1268 CFDataGetLength(sharedSecret),
1269 kCFStringEncodingUTF8,
1270 FALSE);
1271 CFRelease(sharedSecret);
1272 CFDictionarySetValue(new_entity,
1273 kSCPropNetIPSecSharedSecret,
1274 password);
1275 CFRelease(password);
1276 CFDictionaryRemoveValue(new_entity,
1277 kSCPropNetIPSecSharedSecretEncryption);
1278
1279 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
1280 CFDictionarySetValue(new_options, kSCEntNetIPSec, new_entity);
1281 CFRelease(new_entity);
1282
1283 CFRelease(*userOptions);
1284 *userOptions = new_options;
1285 goto done;
1286 }
1287
1288 keychain = _SCSecKeychainCopySystemKeychain();
1289 if (keychain == NULL) {
1290 goto done;
1291 }
1292
1293 if (_SCSecKeychainPasswordItemExists(keychain, keychainID)) {
1294 CFMutableDictionaryRef new_entity;
1295 CFMutableDictionaryRef new_options;
1296
1297 // access SharedSecret from system keychain
1298 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
1299
1300 CFDictionarySetValue(new_entity,
1301 kSCPropNetIPSecSharedSecret,
1302 keychainID);
1303 CFDictionarySetValue(new_entity,
1304 kSCPropNetIPSecSharedSecretEncryption,
1305 kSCValNetIPSecSharedSecretEncryptionKeychain);
1306
1307 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
1308 CFDictionarySetValue(new_options, kSCEntNetIPSec, new_entity);
1309 CFRelease(new_entity);
1310
1311 CFRelease(*userOptions);
1312 *userOptions = new_options;
1313 }
1314
1315 done :
1316
1317 if (keychain != NULL) CFRelease(keychain);
1318 CFRelease(keychainID);
1319 return;
1320 }
1321
1322
1323 static CFDictionaryRef
1324 copyOptionsCallout(CFStringRef serviceID,
1325 CFDictionaryRef current,
1326 void *context1,
1327 void *context2,
1328 void *context3)
1329 {
1330 CFStringRef matchID = (CFStringRef)context1;
1331 CFMutableDictionaryRef *userOptions = (CFMutableDictionaryRef *)context3;
1332
1333 if (current == NULL) {
1334 // we have nothing to "add"
1335 return NULL;
1336 }
1337
1338 if (isMatchingPrefsID(current, matchID)) {
1339 // if we match, return options dictionary
1340 if (*userOptions != NULL) CFRelease(*userOptions);
1341 *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, current);
1342 CFDictionaryRemoveValue(*userOptions, USER_PREFERENCES_ID);
1343 CFDictionaryRemoveValue(*userOptions, USER_PREFERENCES_DEFAULT);
1344 }
1345
1346 return CFRetain(current);
1347 }
1348
1349
1350 Boolean
1351 SCNetworkConnectionStartWithUserPreferences(SCNetworkConnectionRef connection,
1352 SCUserPreferencesRef userPreferences,
1353 Boolean linger)
1354 {
1355 Boolean ok;
1356 CFDictionaryRef userOptions = NULL;
1357 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
1358
1359 if (!isA_SCUserPreferences(userPreferences)) {
1360 _SCErrorSet(kSCStatusInvalidArgument);
1361 return FALSE;
1362 }
1363
1364 (void) processPreferences(userPrivate->serviceID,
1365 copyOptionsCallout,
1366 (void *)userPrivate->prefsID,
1367 NULL,
1368 &userOptions);
1369
1370 /*
1371 * For some legacy preferences, some of the user options
1372 * were missing yet handled by the APIs. Make sure that
1373 * everything still works!
1374 */
1375 if (userOptions != NULL) {
1376 update_PPP_entity (userPreferences, &userOptions);
1377 update_IPSec_entity(userPreferences, &userOptions);
1378 }
1379
1380 ok = SCNetworkConnectionStart(connection, userOptions, linger);
1381
1382 if (userOptions != NULL) {
1383 CFRelease(userOptions);
1384 }
1385
1386 return ok;
1387 }
1388
1389
1390 #pragma mark -
1391 #pragma mark SCUserPreferences + SCNetworkInterface Password SPIs
1392
1393
1394 static CFStringRef
1395 getUserPasswordID(CFDictionaryRef config, SCUserPreferencesRef userPreferences)
1396 {
1397 CFStringRef unique_id = NULL;
1398
1399 if (config != NULL) {
1400 CFStringRef encryption;
1401
1402 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption);
1403 if (isA_CFString(encryption) &&
1404 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
1405 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword);
1406 }
1407 }
1408 if (unique_id == NULL) {
1409 unique_id = SCUserPreferencesGetUniqueID(userPreferences);
1410 }
1411
1412 return unique_id;
1413 }
1414
1415
1416 static CFStringRef
1417 copyUserSharedSecretID(CFDictionaryRef config, SCUserPreferencesRef userPreferences)
1418 {
1419 CFMutableStringRef sharedSecret = NULL;
1420
1421 if (config != NULL) {
1422 CFStringRef encryption;
1423
1424 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption);
1425 if (isA_CFString(encryption) &&
1426 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
1427 sharedSecret = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret);
1428 if (sharedSecret != NULL) {
1429 CFRetain(sharedSecret);
1430 }
1431 }
1432 }
1433
1434 if (sharedSecret == NULL) {
1435 CFStringRef unique_id;
1436
1437 unique_id = getUserPasswordID(config, userPreferences);
1438 sharedSecret = CFStringCreateMutableCopy(NULL, 0, unique_id);
1439 CFStringAppend(sharedSecret, CFSTR(".SS"));
1440 }
1441
1442 return sharedSecret;
1443 }
1444
1445
1446 static CFStringRef
1447 copyUserXAuthID(CFDictionaryRef config, SCUserPreferencesRef userPreferences)
1448 {
1449 CFMutableStringRef xauth_id = NULL;
1450
1451 if (config != NULL) {
1452 CFStringRef encryption;
1453
1454 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPasswordEncryption);
1455 if (isA_CFString(encryption) &&
1456 CFEqual(encryption, kSCValNetIPSecXAuthPasswordEncryptionKeychain)) {
1457 xauth_id = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecXAuthPassword);
1458 if (xauth_id != NULL) {
1459 CFRetain(xauth_id);
1460 }
1461 }
1462 }
1463
1464 if (xauth_id == NULL) {
1465 CFStringRef unique_id;
1466
1467 unique_id = getUserPasswordID(config, userPreferences);
1468 xauth_id = CFStringCreateMutableCopy(NULL, 0, unique_id);
1469 CFStringAppend(xauth_id, CFSTR(".XAUTH"));
1470 }
1471
1472 return xauth_id;
1473 }
1474
1475
1476 static Boolean
1477 checkUserPreferencesPassword(SCUserPreferencesRef userPreferences,
1478 SCNetworkInterfaceRef interface,
1479 SCNetworkInterfacePasswordType passwordType)
1480 {
1481 if (!isA_SCUserPreferences(userPreferences)) {
1482 _SCErrorSet(kSCStatusInvalidArgument);
1483 return FALSE;
1484 }
1485
1486 if (!isA_SCNetworkInterface(interface)) {
1487 _SCErrorSet(kSCStatusInvalidArgument);
1488 return FALSE;
1489 }
1490
1491 switch (passwordType) {
1492 case kSCNetworkInterfacePasswordTypePPP : {
1493 CFStringRef interfaceType;
1494
1495 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1496 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
1497 _SCErrorSet(kSCStatusInvalidArgument);
1498 return FALSE;
1499 }
1500 break;
1501 }
1502
1503 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1504 CFStringRef interfaceType;
1505
1506 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1507 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
1508 _SCErrorSet(kSCStatusInvalidArgument);
1509 return FALSE;
1510 }
1511
1512 interface = SCNetworkInterfaceGetInterface(interface);
1513 if (interface == NULL) {
1514 _SCErrorSet(kSCStatusInvalidArgument);
1515 return FALSE;
1516 }
1517
1518 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1519 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
1520 _SCErrorSet(kSCStatusInvalidArgument);
1521 return FALSE;
1522 }
1523 break;
1524 }
1525
1526 case kSCNetworkInterfacePasswordTypeEAPOL : {
1527 _SCErrorSet(kSCStatusInvalidArgument);
1528 return FALSE;
1529 }
1530
1531 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
1532 CFStringRef interfaceType;
1533
1534 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1535 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) {
1536 _SCErrorSet(kSCStatusInvalidArgument);
1537 return FALSE;
1538 }
1539 break;
1540 }
1541
1542 case kSCNetworkInterfacePasswordTypeVPN : {
1543 CFStringRef interfaceType;
1544
1545 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1546 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) {
1547 _SCErrorSet(kSCStatusInvalidArgument);
1548 return FALSE;
1549 }
1550 break;
1551 }
1552
1553 default :
1554 break;
1555 }
1556
1557 return TRUE;
1558 }
1559
1560
1561 Boolean
1562 SCUserPreferencesCheckInterfacePassword(SCUserPreferencesRef userPreferences,
1563 SCNetworkInterfaceRef interface,
1564 SCNetworkInterfacePasswordType passwordType)
1565 {
1566 Boolean exists = FALSE;
1567
1568 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1569 return FALSE;
1570 }
1571
1572 switch (passwordType) {
1573 case kSCNetworkInterfacePasswordTypePPP : {
1574 CFDictionaryRef config;
1575 CFStringRef unique_id;
1576
1577 // get configuration
1578 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1579
1580 // get userPreferences ID
1581 unique_id = getUserPasswordID(config, userPreferences);
1582
1583 // check
1584 exists = __extract_password(NULL,
1585 config,
1586 kSCPropNetPPPAuthPassword,
1587 kSCPropNetPPPAuthPasswordEncryption,
1588 kSCValNetPPPAuthPasswordEncryptionKeychain,
1589 unique_id,
1590 NULL);
1591
1592 if (config != NULL) CFRelease(config);
1593 break;
1594 }
1595
1596 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1597 CFDictionaryRef config;
1598 CFStringRef shared_id;
1599
1600 // get configuration
1601 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
1602 interface,
1603 kSCEntNetIPSec);
1604
1605 // get sharedSecret ID
1606 shared_id = copyUserSharedSecretID(config, userPreferences);
1607
1608 // check
1609 exists = __extract_password(NULL,
1610 config,
1611 kSCPropNetIPSecSharedSecret,
1612 kSCPropNetIPSecSharedSecretEncryption,
1613 kSCValNetIPSecSharedSecretEncryptionKeychain,
1614 shared_id,
1615 NULL);
1616
1617 if (config != NULL) CFRelease(config);
1618 CFRelease(shared_id);
1619 break;
1620 }
1621
1622 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
1623 CFDictionaryRef config;
1624 CFStringRef xauth_id;
1625
1626 // get configuration
1627 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1628
1629 // get XAuth ID
1630 xauth_id = copyUserXAuthID(config, userPreferences);
1631
1632 // check
1633 exists = __extract_password(NULL,
1634 config,
1635 kSCPropNetIPSecXAuthPassword,
1636 kSCPropNetIPSecXAuthPasswordEncryption,
1637 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
1638 xauth_id,
1639 NULL);
1640
1641 if (config != NULL) CFRelease(config);
1642 CFRelease(xauth_id);
1643 break;
1644 }
1645
1646 case kSCNetworkInterfacePasswordTypeVPN : {
1647 CFDictionaryRef config;
1648 CFStringRef unique_id;
1649
1650 // get configuration
1651 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1652
1653 // get userPreferences ID
1654 unique_id = getUserPasswordID(config, userPreferences);
1655
1656 // check
1657 exists = __extract_password(NULL,
1658 config,
1659 kSCPropNetVPNAuthPassword,
1660 kSCPropNetVPNAuthPasswordEncryption,
1661 kSCValNetVPNAuthPasswordEncryptionKeychain,
1662 unique_id,
1663 NULL);
1664
1665 if (config != NULL) CFRelease(config);
1666 break;
1667 }
1668
1669 default :
1670 _SCErrorSet(kSCStatusInvalidArgument);
1671 return FALSE;
1672 }
1673
1674 return exists;
1675 }
1676
1677
1678 CFDataRef
1679 SCUserPreferencesCopyInterfacePassword(SCUserPreferencesRef userPreferences,
1680 SCNetworkInterfaceRef interface,
1681 SCNetworkInterfacePasswordType passwordType)
1682 {
1683 CFDataRef password = NULL;
1684
1685 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1686 return FALSE;
1687 }
1688
1689 switch (passwordType) {
1690 case kSCNetworkInterfacePasswordTypePPP : {
1691 CFDictionaryRef config;
1692 CFStringRef unique_id;
1693
1694 // get configuration
1695 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1696
1697 // get userPreferences ID
1698 unique_id = getUserPasswordID(config, userPreferences);
1699
1700 // extract
1701 (void) __extract_password(NULL,
1702 config,
1703 kSCPropNetPPPAuthPassword,
1704 kSCPropNetPPPAuthPasswordEncryption,
1705 kSCValNetPPPAuthPasswordEncryptionKeychain,
1706 unique_id,
1707 &password);
1708
1709 if (config != NULL) CFRelease(config);
1710 break;
1711 }
1712
1713 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1714 CFDictionaryRef config;
1715 CFStringRef shared_id;
1716
1717 // get configuration
1718 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
1719 interface,
1720 kSCEntNetIPSec);
1721
1722 // get sharedSecret ID
1723 shared_id = copyUserSharedSecretID(config, userPreferences);
1724
1725 // extract
1726 (void) __extract_password(NULL,
1727 config,
1728 kSCPropNetIPSecSharedSecret,
1729 kSCPropNetIPSecSharedSecretEncryption,
1730 kSCValNetIPSecSharedSecretEncryptionKeychain,
1731 shared_id,
1732 &password);
1733
1734 if (config != NULL) CFRelease(config);
1735 CFRelease(shared_id);
1736 break;
1737 }
1738
1739 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
1740 CFDictionaryRef config;
1741 CFStringRef xauth_id;
1742
1743 // get configuration
1744 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1745
1746 // get XAuth ID
1747 xauth_id = copyUserXAuthID(config, userPreferences);
1748
1749 // extract
1750 (void) __extract_password(NULL,
1751 config,
1752 kSCPropNetIPSecXAuthPassword,
1753 kSCPropNetIPSecXAuthPasswordEncryption,
1754 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
1755 xauth_id,
1756 &password);
1757
1758 if (config != NULL) CFRelease(config);
1759 CFRelease(xauth_id);
1760 break;
1761 }
1762
1763 case kSCNetworkInterfacePasswordTypeVPN : {
1764 CFDictionaryRef config;
1765 CFStringRef unique_id;
1766
1767 // get configuration
1768 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1769
1770 // get userPreferences ID
1771 unique_id = getUserPasswordID(config, userPreferences);
1772
1773 // extract
1774 (void) __extract_password(NULL,
1775 config,
1776 kSCPropNetVPNAuthPassword,
1777 kSCPropNetVPNAuthPasswordEncryption,
1778 kSCValNetVPNAuthPasswordEncryptionKeychain,
1779 unique_id,
1780 &password);
1781
1782 if (config != NULL) CFRelease(config);
1783 break;
1784 }
1785
1786 default :
1787 _SCErrorSet(kSCStatusInvalidArgument);
1788 return NULL;
1789 }
1790
1791 return password;
1792 }
1793
1794
1795 Boolean
1796 SCUserPreferencesRemoveInterfacePassword(SCUserPreferencesRef userPreferences,
1797 SCNetworkInterfaceRef interface,
1798 SCNetworkInterfacePasswordType passwordType)
1799 {
1800 Boolean ok = FALSE;
1801
1802 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1803 return FALSE;
1804 }
1805
1806 switch (passwordType) {
1807 case kSCNetworkInterfacePasswordTypePPP : {
1808 CFDictionaryRef config;
1809 CFDictionaryRef newConfig = NULL;
1810 CFStringRef unique_id;
1811
1812 // get configuration
1813 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1814
1815 // get userPreferences ID
1816 unique_id = getUserPasswordID(config, userPreferences);
1817
1818 // remove password
1819 ok = __remove_password(NULL,
1820 config,
1821 kSCPropNetPPPAuthPassword,
1822 kSCPropNetPPPAuthPasswordEncryption,
1823 kSCValNetPPPAuthPasswordEncryptionKeychain,
1824 unique_id,
1825 &newConfig);
1826 if (ok) {
1827 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
1828 if (newConfig != NULL) CFRelease(newConfig);
1829 }
1830
1831 if (config != NULL) CFRelease(config);
1832 break;
1833 }
1834
1835 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1836 CFDictionaryRef config;
1837 CFDictionaryRef newConfig = NULL;
1838 CFStringRef shared_id;
1839
1840 // get configuration
1841 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
1842 interface,
1843 kSCEntNetIPSec);
1844
1845 // get sharedSecret ID
1846 shared_id = copyUserSharedSecretID(config, userPreferences);
1847
1848 // remove password
1849 ok = __remove_password(NULL,
1850 config,
1851 kSCPropNetIPSecSharedSecret,
1852 kSCPropNetIPSecSharedSecretEncryption,
1853 kSCValNetIPSecSharedSecretEncryptionKeychain,
1854 shared_id,
1855 &newConfig);
1856 if (ok) {
1857 ok = SCUserPreferencesSetExtendedInterfaceConfiguration(userPreferences,
1858 interface,
1859 kSCEntNetIPSec,
1860 newConfig);
1861 if (newConfig != NULL) CFRelease(newConfig);
1862 }
1863
1864 if (config != NULL) CFRelease(config);
1865 CFRelease(shared_id);
1866 break;
1867 }
1868
1869 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
1870 CFDictionaryRef config;
1871 CFDictionaryRef newConfig = NULL;
1872 CFStringRef xauth_id;
1873
1874 // get configuration
1875 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1876
1877 // get XAuth ID
1878 xauth_id = copyUserXAuthID(config, userPreferences);
1879
1880 // remove password
1881 ok = __remove_password(NULL,
1882 config,
1883 kSCPropNetIPSecXAuthPassword,
1884 kSCPropNetIPSecXAuthPasswordEncryption,
1885 kSCValNetIPSecXAuthPasswordEncryptionKeychain,
1886 xauth_id,
1887 &newConfig);
1888 if (ok) {
1889 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
1890 if (newConfig != NULL) CFRelease(newConfig);
1891 }
1892
1893 if (config != NULL) CFRelease(config);
1894 CFRelease(xauth_id);
1895 break;
1896 }
1897
1898 case kSCNetworkInterfacePasswordTypeVPN : {
1899 CFDictionaryRef config;
1900 CFDictionaryRef newConfig = NULL;
1901 CFStringRef unique_id;
1902
1903 // get configuration
1904 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1905
1906 // get userPreferences ID
1907 unique_id = getUserPasswordID(config, userPreferences);
1908
1909 // remove password
1910 ok = __remove_password(NULL,
1911 config,
1912 kSCPropNetVPNAuthPassword,
1913 kSCPropNetVPNAuthPasswordEncryption,
1914 kSCValNetVPNAuthPasswordEncryptionKeychain,
1915 unique_id,
1916 &newConfig);
1917 if (ok) {
1918 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
1919 if (newConfig != NULL) CFRelease(newConfig);
1920 }
1921
1922 if (config != NULL) CFRelease(config);
1923 break;
1924 }
1925
1926 default :
1927 _SCErrorSet(kSCStatusInvalidArgument);
1928 return FALSE;
1929 }
1930
1931 return ok;
1932 }
1933
1934
1935 Boolean
1936 SCUserPreferencesSetInterfacePassword(SCUserPreferencesRef userPreferences,
1937 SCNetworkInterfaceRef interface,
1938 SCNetworkInterfacePasswordType passwordType,
1939 CFDataRef password,
1940 CFDictionaryRef options)
1941 {
1942 CFStringRef account = NULL;
1943 CFBundleRef bundle;
1944 CFDictionaryRef config;
1945 CFStringRef description = NULL;
1946 CFStringRef label = NULL;
1947 Boolean ok = FALSE;
1948
1949 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1950 return FALSE;
1951 }
1952
1953 bundle = _SC_CFBundleGet();
1954
1955 switch (passwordType) {
1956 case kSCNetworkInterfacePasswordTypePPP : {
1957 CFStringRef unique_id;
1958
1959 // get configuration
1960 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1961
1962 // get userPreferences ID
1963 unique_id = getUserPasswordID(config, userPreferences);
1964
1965 // User prefs auth name --> keychain "Account"
1966 if (config != NULL) {
1967 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName);
1968 }
1969
1970 // User prefs "name" --> keychain "Name"
1971 label = SCUserPreferencesCopyName(userPreferences);
1972
1973 // "PPP Password" --> keychain "Kind"
1974 if (bundle != NULL) {
1975 description = CFBundleCopyLocalizedString(bundle,
1976 CFSTR("KEYCHAIN_KIND_PPP_PASSWORD"),
1977 CFSTR("PPP Password"),
1978 NULL);
1979 }
1980
1981 // store password
1982 ok = _SCSecKeychainPasswordItemSet(NULL,
1983 unique_id,
1984 (label != NULL) ? label : CFSTR("Network Connection"),
1985 (description != NULL) ? description : CFSTR("PPP Password"),
1986 account,
1987 password,
1988 options);
1989 if (ok) {
1990 CFMutableDictionaryRef newConfig;
1991
1992 if (config != NULL) {
1993 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
1994 } else {
1995 newConfig = CFDictionaryCreateMutable(NULL,
1996 0,
1997 &kCFTypeDictionaryKeyCallBacks,
1998 &kCFTypeDictionaryValueCallBacks);
1999 }
2000 CFDictionarySetValue(newConfig,
2001 kSCPropNetPPPAuthPassword,
2002 unique_id);
2003 CFDictionarySetValue(newConfig,
2004 kSCPropNetPPPAuthPasswordEncryption,
2005 kSCValNetPPPAuthPasswordEncryptionKeychain);
2006 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
2007 CFRelease(newConfig);
2008 }
2009
2010 if (config != NULL) CFRelease(config);
2011 if (description != NULL) CFRelease(description);
2012 if (label != NULL) CFRelease(label);
2013 break;
2014 }
2015
2016 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
2017 CFStringRef shared_id;
2018
2019 // get configuration
2020 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
2021 interface,
2022 kSCEntNetIPSec);
2023
2024 // get sharedSecret ID
2025 shared_id = copyUserSharedSecretID(config, userPreferences);
2026
2027 // User prefs "name" --> keychain "Name"
2028 label = SCUserPreferencesCopyName(userPreferences);
2029
2030 // "IPSec Shared Secret" --> keychain "Kind"
2031 if (bundle != NULL) {
2032 description = CFBundleCopyLocalizedString(bundle,
2033 CFSTR("KEYCHAIN_KIND_IPSEC_SHARED_SECRET"),
2034 CFSTR("IPSec Shared Secret"),
2035 NULL);
2036 }
2037
2038 // set password
2039 ok = _SCSecKeychainPasswordItemSet(NULL,
2040 shared_id,
2041 (label != NULL) ? label : CFSTR("Network Connection"),
2042 (description != NULL) ? description : CFSTR("IPSec Shared Secret"),
2043 NULL,
2044 password,
2045 options);
2046 if (ok) {
2047 CFMutableDictionaryRef newConfig = NULL;
2048
2049 if (config != NULL) {
2050 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
2051 } else {
2052 newConfig = CFDictionaryCreateMutable(NULL,
2053 0,
2054 &kCFTypeDictionaryKeyCallBacks,
2055 &kCFTypeDictionaryValueCallBacks);
2056 }
2057 CFDictionarySetValue(newConfig,
2058 kSCPropNetIPSecSharedSecret,
2059 shared_id);
2060 CFDictionarySetValue(newConfig,
2061 kSCPropNetIPSecSharedSecretEncryption,
2062 kSCValNetIPSecSharedSecretEncryptionKeychain);
2063 ok = SCUserPreferencesSetExtendedInterfaceConfiguration(userPreferences,
2064 interface,
2065 kSCEntNetIPSec,
2066 newConfig);
2067 CFRelease(newConfig);
2068 }
2069
2070 if (config != NULL) CFRelease(config);
2071 if (description != NULL) CFRelease(description);
2072 if (label != NULL) CFRelease(label);
2073 CFRelease(shared_id);
2074 break;
2075 }
2076
2077 case kSCNetworkInterfacePasswordTypeIPSecXAuth : {
2078 CFStringRef xauth_id;
2079
2080 // get configuration
2081 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
2082
2083 // get XAuth ID
2084 xauth_id = copyUserXAuthID(config, userPreferences);
2085
2086 // User prefs XAuth name --> keychain "Account"
2087 if (config != NULL) {
2088 account = CFDictionaryGetValue(config, kSCPropNetIPSecXAuthName);
2089 }
2090
2091 // User prefs "name" --> keychain "Name"
2092 label = SCUserPreferencesCopyName(userPreferences);
2093
2094 // "IPSec XAuth Password" --> keychain "Kind"
2095 if (bundle != NULL) {
2096 description = CFBundleCopyLocalizedString(bundle,
2097 CFSTR("KEYCHAIN_KIND_IPSEC_XAUTH_PASSWORD"),
2098 CFSTR("IPSec XAuth Password"),
2099 NULL);
2100 }
2101
2102 // store password
2103 ok = _SCSecKeychainPasswordItemSet(NULL,
2104 xauth_id,
2105 (label != NULL) ? label : CFSTR("Network Connection"),
2106 (description != NULL) ? description : CFSTR("IPSec XAuth Password"),
2107 account,
2108 password,
2109 options);
2110 if (ok) {
2111 CFMutableDictionaryRef newConfig;
2112
2113 if (config != NULL) {
2114 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
2115 } else {
2116 newConfig = CFDictionaryCreateMutable(NULL,
2117 0,
2118 &kCFTypeDictionaryKeyCallBacks,
2119 &kCFTypeDictionaryValueCallBacks);
2120 }
2121 CFDictionarySetValue(newConfig,
2122 kSCPropNetIPSecXAuthPassword,
2123 xauth_id);
2124 CFDictionarySetValue(newConfig,
2125 kSCPropNetIPSecXAuthPasswordEncryption,
2126 kSCValNetIPSecXAuthPasswordEncryptionKeychain);
2127 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
2128 CFRelease(newConfig);
2129 }
2130
2131 if (config != NULL) CFRelease(config);
2132 if (description != NULL) CFRelease(description);
2133 if (label != NULL) CFRelease(label);
2134 CFRelease(xauth_id);
2135 break;
2136 }
2137
2138 case kSCNetworkInterfacePasswordTypeVPN : {
2139 CFStringRef unique_id;
2140
2141 // get configuration
2142 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
2143
2144 // get userPreferences ID
2145 unique_id = getUserPasswordID(config, userPreferences);
2146
2147 // User prefs auth name --> keychain "Account"
2148 if (config != NULL) {
2149 account = CFDictionaryGetValue(config, kSCPropNetVPNAuthName);
2150 }
2151
2152 // User prefs "name" --> keychain "Name"
2153 label = SCUserPreferencesCopyName(userPreferences);
2154
2155 // "VPN Password" --> keychain "Kind"
2156 if (bundle != NULL) {
2157 description = CFBundleCopyLocalizedString(bundle,
2158 CFSTR("KEYCHAIN_KIND_VPN_PASSWORD"),
2159 CFSTR("VPN Password"),
2160 NULL);
2161 }
2162
2163 // store password
2164 ok = _SCSecKeychainPasswordItemSet(NULL,
2165 unique_id,
2166 (label != NULL) ? label : CFSTR("Network Connection"),
2167 (description != NULL) ? description : CFSTR("VPN Password"),
2168 account,
2169 password,
2170 options);
2171 if (ok) {
2172 CFMutableDictionaryRef newConfig;
2173
2174 if (config != NULL) {
2175 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
2176 } else {
2177 newConfig = CFDictionaryCreateMutable(NULL,
2178 0,
2179 &kCFTypeDictionaryKeyCallBacks,
2180 &kCFTypeDictionaryValueCallBacks);
2181 }
2182 CFDictionarySetValue(newConfig,
2183 kSCPropNetVPNAuthPassword,
2184 unique_id);
2185 CFDictionarySetValue(newConfig,
2186 kSCPropNetVPNAuthPasswordEncryption,
2187 kSCValNetVPNAuthPasswordEncryptionKeychain);
2188 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
2189 CFRelease(newConfig);
2190 }
2191
2192 if (config != NULL) CFRelease(config);
2193 if (description != NULL) CFRelease(description);
2194 if (label != NULL) CFRelease(label);
2195 break;
2196 }
2197
2198 default :
2199 _SCErrorSet(kSCStatusInvalidArgument);
2200 return FALSE;
2201 }
2202
2203 return ok;
2204 }