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