]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkConnectionPrivate.c
configd-212.2.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkConnectionPrivate.c
1 /*
2 * Copyright (c) 2006, 2007 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 #include <ppp/PPPControllerPriv.h>
32
33
34 #pragma mark -
35 #pragma mark SCUserPreferences
36
37
38 typedef struct {
39
40 // base CFType information
41 CFRuntimeBase cfBase;
42
43 // serviceID
44 CFStringRef serviceID;
45
46 // user preferences [unique] id
47 CFStringRef prefsID;
48
49 } SCUserPreferencesPrivate, *SCUserPreferencesPrivateRef;
50
51
52 static CFStringRef __SCUserPreferencesCopyDescription (CFTypeRef cf);
53 static void __SCUserPreferencesDeallocate (CFTypeRef cf);
54 static Boolean __SCUserPreferencesEqual (CFTypeRef cf1, CFTypeRef cf2);
55 static CFHashCode __SCUserPreferencesHash (CFTypeRef cf);
56
57
58 static CFTypeID __kSCUserPreferencesTypeID = _kCFRuntimeNotATypeID;
59
60
61 static const CFRuntimeClass __SCUserPreferencesClass = {
62 0, // version
63 "SCUserPreferences", // className
64 NULL, // init
65 NULL, // copy
66 __SCUserPreferencesDeallocate, // dealloc
67 __SCUserPreferencesEqual, // equal
68 __SCUserPreferencesHash, // hash
69 NULL, // copyFormattingDesc
70 __SCUserPreferencesCopyDescription // copyDebugDesc
71 };
72
73
74 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
75
76
77 static CFStringRef
78 __SCUserPreferencesCopyDescription(CFTypeRef cf)
79 {
80 CFAllocatorRef allocator = CFGetAllocator(cf);
81 CFMutableStringRef result;
82 SCUserPreferencesPrivateRef prefsPrivate = (SCUserPreferencesPrivateRef)cf;
83
84 result = CFStringCreateMutable(allocator, 0);
85 CFStringAppendFormat(result, NULL, CFSTR("<SCUserPreferences %p [%p]> {"), cf, allocator);
86 CFStringAppendFormat(result, NULL, CFSTR("service = %@"), prefsPrivate->serviceID);
87 CFStringAppendFormat(result, NULL, CFSTR(", id = %@"), prefsPrivate->prefsID);
88 CFStringAppendFormat(result, NULL, CFSTR("}"));
89
90 return result;
91 }
92
93
94 static void
95 __SCUserPreferencesDeallocate(CFTypeRef cf)
96 {
97 SCUserPreferencesPrivateRef prefsPrivate = (SCUserPreferencesPrivateRef)cf;
98
99 /* release resources */
100
101 CFRelease(prefsPrivate->prefsID);
102 CFRelease(prefsPrivate->serviceID);
103
104 return;
105 }
106
107
108 static Boolean
109 __SCUserPreferencesEqual(CFTypeRef cf1, CFTypeRef cf2)
110 {
111 SCUserPreferencesPrivateRef s1 = (SCUserPreferencesPrivateRef)cf1;
112 SCUserPreferencesPrivateRef s2 = (SCUserPreferencesPrivateRef)cf2;
113
114 if (s1 == s2)
115 return TRUE;
116
117 if (!CFEqual(s1->prefsID, s2->prefsID))
118 return FALSE; // if not the same [unique] prefs identifier
119
120 return TRUE;
121 }
122
123
124 static CFHashCode
125 __SCUserPreferencesHash(CFTypeRef cf)
126 {
127 SCUserPreferencesPrivateRef prefsPrivate = (SCUserPreferencesPrivateRef)cf;
128
129 return CFHash(prefsPrivate->prefsID);
130 }
131
132
133 static void
134 __SCUserPreferencesInitialize(void)
135 {
136 __kSCUserPreferencesTypeID = _CFRuntimeRegisterClass(&__SCUserPreferencesClass);
137 return;
138 }
139
140
141 static SCUserPreferencesPrivateRef
142 __SCUserPreferencesCreatePrivate(CFAllocatorRef allocator,
143 CFStringRef serviceID,
144 CFStringRef prefsID)
145 {
146 SCUserPreferencesPrivateRef prefsPrivate;
147 uint32_t size;
148
149 /* initialize runtime */
150 pthread_once(&initialized, __SCUserPreferencesInitialize);
151
152 /* allocate target */
153 size = sizeof(SCUserPreferencesPrivate) - sizeof(CFRuntimeBase);
154 prefsPrivate = (SCUserPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
155 __kSCUserPreferencesTypeID,
156 size,
157 NULL);
158 if (prefsPrivate == NULL) {
159 return NULL;
160 }
161
162 prefsPrivate->serviceID = CFStringCreateCopy(NULL, serviceID);
163 prefsPrivate->prefsID = CFStringCreateCopy(NULL, prefsID);
164
165 return prefsPrivate;
166 }
167
168
169 static __inline__ CFTypeRef
170 isA_SCUserPreferences(CFTypeRef obj)
171 {
172 return (isA_CFType(obj, SCUserPreferencesGetTypeID()));
173 }
174
175
176 #pragma mark -
177 #pragma mark SCUserPreferences SPIs
178
179
180 #define USER_PREFERENCES_NOTIFICATION "com.apple.networkConnect"
181 #define USER_PREFERENCES_APPLICATION_ID CFSTR("com.apple.networkConnect")
182 #define USER_PREFERENCES_ID CFSTR("UniqueIdentifier")
183 #define USER_PREFERENCES_DEFAULT CFSTR("ConnectByDefault")
184
185
186 static CFArrayRef
187 copyCFPreferencesForServiceID(CFStringRef serviceID)
188 {
189 CFArrayRef prefs;
190
191 // fetch "Managed" or "ByHost" user preferences
192 (void) CFPreferencesAppSynchronize(USER_PREFERENCES_APPLICATION_ID);
193 prefs = CFPreferencesCopyAppValue(serviceID,
194 USER_PREFERENCES_APPLICATION_ID);
195
196 if ((prefs != NULL) && !isA_CFArray(prefs)) {
197 CFRelease(prefs);
198 return NULL;
199 }
200
201 return prefs;
202 }
203
204
205 static Boolean
206 setCFPreferencesForServiceID(CFStringRef serviceID, CFArrayRef newPreferences)
207 {
208 Boolean ok;
209
210 if (CFPreferencesAppValueIsForced(serviceID, USER_PREFERENCES_APPLICATION_ID)) {
211 return FALSE;
212 }
213
214 CFPreferencesSetValue(serviceID,
215 newPreferences,
216 USER_PREFERENCES_APPLICATION_ID,
217 kCFPreferencesCurrentUser,
218 kCFPreferencesCurrentHost);
219 ok = CFPreferencesSynchronize(USER_PREFERENCES_APPLICATION_ID,
220 kCFPreferencesCurrentUser,
221 kCFPreferencesCurrentHost);
222
223 (void) notify_post(USER_PREFERENCES_NOTIFICATION);
224
225 return ok;
226 }
227
228
229 static void
230 addPreference(CFMutableArrayRef *newPrefs, CFDictionaryRef newDict)
231 {
232 if (*newPrefs == NULL) {
233 *newPrefs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
234 }
235 CFArrayAppendValue(*newPrefs, newDict);
236
237 return;
238 }
239
240
241 typedef CFDictionaryRef (*processPreferencesCallout) (CFStringRef serviceID,
242 CFDictionaryRef current,
243 void *context1,
244 void *context2,
245 void *context3);
246
247
248 static Boolean
249 processPreferences(CFStringRef serviceID,
250 processPreferencesCallout callout,
251 void *context1,
252 void *context2,
253 void *context3)
254 {
255 Boolean changed = FALSE;
256 CFIndex i;
257 CFIndex n;
258 CFDictionaryRef newDict = NULL;
259 CFMutableArrayRef newPrefs = NULL;
260 Boolean ok = TRUE;
261 CFArrayRef prefs;
262
263 prefs = copyCFPreferencesForServiceID(serviceID);
264 n = (prefs != NULL) ? CFArrayGetCount(prefs) : 0;
265 for (i = 0; i < n; i++) {
266 CFDictionaryRef dict;
267
268 dict = CFArrayGetValueAtIndex(prefs, i);
269 if (isA_CFDictionary(dict)) {
270 newDict = (*callout)(serviceID, dict, context1, context2, context3);
271 if (newDict == NULL) {
272 // if entry to be removed
273 changed = TRUE;
274 continue;
275 }
276 } else {
277 // if not a CFDictionary, leave as-is
278 newDict = CFRetain(dict);
279 }
280
281 if (!CFEqual(dict, newDict)) {
282 changed = TRUE;
283 }
284
285 addPreference(&newPrefs, newDict);
286 CFRelease(newDict);
287 }
288 if (prefs != NULL) CFRelease(prefs);
289
290 newDict = (*callout)(serviceID, NULL, context1, context2, context3);
291 if (newDict != NULL) {
292 // if new entry
293 changed = TRUE;
294 addPreference(&newPrefs, newDict);
295 CFRelease(newDict);
296 }
297
298 if (changed) {
299 ok = setCFPreferencesForServiceID(serviceID, newPrefs);
300 }
301 if (newPrefs != NULL) CFRelease(newPrefs);
302
303 return ok;
304 }
305
306
307 static __inline__ Boolean
308 isMatchingPrefsID(CFDictionaryRef dict, CFStringRef matchID)
309 {
310 CFStringRef prefsID;
311
312 prefsID = CFDictionaryGetValue(dict, USER_PREFERENCES_ID);
313 if (isA_CFString(prefsID)) {
314 if (CFEqual(prefsID, matchID)) {
315 return TRUE;
316 }
317 }
318
319 return FALSE;
320 }
321
322
323 CFTypeID
324 SCUserPreferencesGetTypeID(void)
325 {
326 pthread_once(&initialized, __SCUserPreferencesInitialize); /* initialize runtime */
327 return __kSCUserPreferencesTypeID;
328 }
329
330
331 CFStringRef
332 SCUserPreferencesGetUniqueID(SCUserPreferencesRef userPreferences)
333 {
334 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
335
336 if (!isA_SCUserPreferences(userPreferences)) {
337 _SCErrorSet(kSCStatusInvalidArgument);
338 return FALSE;
339 }
340
341 return userPrivate->prefsID;
342 }
343
344
345 Boolean
346 SCUserPreferencesIsForced(SCUserPreferencesRef userPreferences)
347 {
348 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
349
350 if (!isA_SCUserPreferences(userPreferences)) {
351 _SCErrorSet(kSCStatusInvalidArgument);
352 return FALSE;
353 }
354
355 return CFPreferencesAppValueIsForced(userPrivate->serviceID, USER_PREFERENCES_APPLICATION_ID);
356 }
357
358
359 static CFDictionaryRef
360 removeCallout(CFStringRef serviceID,
361 CFDictionaryRef current,
362 void *context1,
363 void *context2,
364 void *context3)
365 {
366 CFStringRef matchID = (CFStringRef)context1;
367
368 if (current == NULL) {
369 // we have nothing to "add"
370 return NULL;
371 }
372
373 if (isMatchingPrefsID(current, matchID)) {
374 // if we match, don't add (i.e. remove)
375 return NULL;
376 }
377
378 return CFRetain(current);
379 }
380
381
382 Boolean
383 SCUserPreferencesRemove(SCUserPreferencesRef userPreferences)
384 {
385 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
386
387 if (!isA_SCUserPreferences(userPreferences)) {
388 _SCErrorSet(kSCStatusInvalidArgument);
389 return FALSE;
390 }
391
392 return processPreferences(userPrivate->serviceID,
393 removeCallout,
394 (void *)userPrivate->prefsID,
395 NULL,
396 NULL);
397 }
398
399
400 static CFDictionaryRef
401 setCurrentCallout(CFStringRef serviceID,
402 CFDictionaryRef current,
403 void *context1,
404 void *context2,
405 void *context3)
406 {
407 CFStringRef matchID = (CFStringRef)context1;
408 CFMutableDictionaryRef newDict;
409
410 if (current == NULL) {
411 // we have nothing to "add"
412 return NULL;
413 }
414
415 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current);
416
417 // remove "default" flag
418 CFDictionaryRemoveValue(newDict, USER_PREFERENCES_DEFAULT);
419
420 if (isMatchingPrefsID(current, matchID)) {
421 // if we match, set "default" flag
422 CFDictionarySetValue(newDict, USER_PREFERENCES_DEFAULT, kCFBooleanTrue);
423 }
424
425 return newDict;
426 }
427
428
429 Boolean
430 SCUserPreferencesSetCurrent(SCUserPreferencesRef userPreferences)
431 {
432 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
433
434 if (!isA_SCUserPreferences(userPreferences)) {
435 _SCErrorSet(kSCStatusInvalidArgument);
436 return FALSE;
437 }
438
439 return processPreferences(userPrivate->serviceID,
440 setCurrentCallout,
441 (void *)userPrivate->prefsID,
442 NULL,
443 NULL);
444 }
445
446
447 static CFDictionaryRef
448 copyNameCallout(CFStringRef serviceID,
449 CFDictionaryRef current,
450 void *context1,
451 void *context2,
452 void *context3)
453 {
454 CFStringRef matchID = (CFStringRef)context1;
455 CFStringRef *name = (CFStringRef *)context3;
456
457 if (current == NULL) {
458 // we have nothing to "add"
459 return NULL;
460 }
461
462 if (isMatchingPrefsID(current, matchID)) {
463 *name = CFDictionaryGetValue(current, kSCPropUserDefinedName);
464
465 // for backwards compatibility, we also check for the name in the PPP entity
466 if (*name == NULL) {
467 CFDictionaryRef ppp;
468
469 ppp = CFDictionaryGetValue(current, kSCEntNetPPP);
470 if (isA_CFDictionary(ppp)) {
471 *name = CFDictionaryGetValue(ppp, kSCPropUserDefinedName);
472 }
473 }
474
475 *name = isA_CFString(*name);
476 if (*name != NULL) {
477 CFRetain(*name);
478 }
479 }
480
481 return CFRetain(current);
482 }
483
484
485 CFStringRef
486 SCUserPreferencesCopyName(SCUserPreferencesRef userPreferences)
487 {
488 CFStringRef name = NULL;
489 Boolean ok;
490 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
491
492 if (!isA_SCUserPreferences(userPreferences)) {
493 _SCErrorSet(kSCStatusInvalidArgument);
494 return FALSE;
495 }
496
497 // find SCUserPreferences and copy name
498 ok = processPreferences(userPrivate->serviceID,
499 copyNameCallout,
500 (void *)userPrivate->prefsID,
501 NULL,
502 (void *)&name);
503 if (!ok) {
504 if (name != NULL) {
505 CFRelease(name);
506 name = NULL;
507 }
508 }
509
510 return name;
511 }
512
513
514 static CFDictionaryRef
515 setNameCallout(CFStringRef serviceID,
516 CFDictionaryRef current,
517 void *context1,
518 void *context2,
519 void *context3)
520 {
521 CFStringRef matchID = (CFStringRef)context1;
522 CFMutableDictionaryRef newDict;
523 CFStringRef newName = (CFStringRef)context2;
524
525 if (current == NULL) {
526 // we have nothing to "add"
527 return NULL;
528 }
529
530 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current);
531
532 if (isMatchingPrefsID(current, matchID)) {
533 CFDictionaryRef pppEntity;
534
535 // set the name
536 if (newName != NULL) {
537 CFDictionarySetValue(newDict, kSCPropUserDefinedName, newName);
538 } else {
539 CFDictionaryRemoveValue(newDict, kSCPropUserDefinedName);
540 }
541
542 // for backwards compatibility, we also set the name in the PPP entity
543 pppEntity = CFDictionaryGetValue(newDict, kSCEntNetPPP);
544 if (isA_CFDictionary(pppEntity)) {
545 CFMutableDictionaryRef newPPPEntity;
546
547 newPPPEntity = CFDictionaryCreateMutableCopy(NULL, 0, pppEntity);
548 if (newName != NULL) {
549 CFDictionarySetValue(newPPPEntity, kSCPropUserDefinedName, newName);
550 } else {
551 CFDictionaryRemoveValue(newPPPEntity, kSCPropUserDefinedName);
552 }
553 CFDictionarySetValue(newDict, kSCEntNetPPP, newPPPEntity);
554 CFRelease(newPPPEntity);
555 }
556 }
557
558 return newDict;
559 }
560
561
562 Boolean
563 SCUserPreferencesSetName(SCUserPreferencesRef userPreferences, CFStringRef newName)
564 {
565 Boolean ok;
566 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
567
568 if (!isA_SCUserPreferences(userPreferences)) {
569 _SCErrorSet(kSCStatusInvalidArgument);
570 return FALSE;
571 }
572
573 if ((newName != NULL) && !isA_CFString(newName)) {
574 _SCErrorSet(kSCStatusInvalidArgument);
575 return FALSE;
576 }
577
578 // find SCUserPreferences and set name
579 ok = processPreferences(userPrivate->serviceID,
580 setNameCallout,
581 (void *)userPrivate->prefsID,
582 (void *)newName,
583 NULL);
584
585 return ok;
586 }
587
588
589 static CFDictionaryRef
590 copyInterfaceConfigurationCallout(CFStringRef serviceID,
591 CFDictionaryRef current,
592 void *context1,
593 void *context2,
594 void *context3)
595 {
596 CFDictionaryRef *dict = (CFDictionaryRef *)context3;
597 CFStringRef interfaceType = (CFStringRef)context2;
598 CFStringRef matchID = (CFStringRef)context1;
599
600 if (current == NULL) {
601 // we have nothing to "add"
602 return NULL;
603 }
604
605 if (isMatchingPrefsID(current, matchID)) {
606 *dict = CFDictionaryGetValue(current, interfaceType);
607 *dict = isA_CFDictionary(*dict);
608 if (*dict != NULL) {
609 CFRetain(*dict);
610 }
611 }
612
613 return CFRetain(current);
614 }
615
616
617 CFDictionaryRef
618 SCUserPreferencesCopyInterfaceConfiguration(SCUserPreferencesRef userPreferences,
619 SCNetworkInterfaceRef interface)
620 {
621 CFStringRef defaultType;
622 CFDictionaryRef entity = NULL;
623 Boolean ok;
624 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
625
626 if (!isA_SCUserPreferences(userPreferences)) {
627 _SCErrorSet(kSCStatusInvalidArgument);
628 return NULL;
629 }
630
631 if (!isA_SCNetworkInterface(interface)) {
632 _SCErrorSet(kSCStatusInvalidArgument);
633 return NULL;
634 }
635
636 // get InterfaceType
637 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
638 if (defaultType == NULL) {
639 _SCErrorSet(kSCStatusInvalidArgument);
640 return NULL;
641 }
642
643 // find SCUserPreferences and copy interface entity
644 ok = processPreferences(userPrivate->serviceID,
645 copyInterfaceConfigurationCallout,
646 (void *)userPrivate->prefsID,
647 (void *)defaultType,
648 (void *)&entity);
649 if (!ok) {
650 if (entity != NULL) {
651 CFRelease(entity);
652 entity = NULL;
653 }
654 }
655
656 return entity;
657 }
658
659
660 static CFDictionaryRef
661 setInterfaceConfigurationCallout(CFStringRef serviceID,
662 CFDictionaryRef current,
663 void *context1,
664 void *context2,
665 void *context3)
666 {
667 CFStringRef interfaceType = (CFStringRef)context2;
668 CFStringRef matchID = (CFStringRef)context1;
669 CFMutableDictionaryRef newDict;
670 CFDictionaryRef newOptions = (CFDictionaryRef)context3;
671
672 if (current == NULL) {
673 // we have nothing to "add"
674 return NULL;
675 }
676
677 newDict = CFDictionaryCreateMutableCopy(NULL, 0, current);
678
679 if (isMatchingPrefsID(current, matchID)) {
680 if (newOptions != NULL) {
681 CFDictionarySetValue(newDict, interfaceType, newOptions);
682
683 // for backwards compatibility, we want to ensure that
684 // the name is set in both the top level and in the PPP
685 // entity.
686 if (CFEqual(interfaceType, kSCEntNetPPP)) {
687 CFStringRef name;
688
689 name = CFDictionaryGetValue(newOptions, kSCPropUserDefinedName);
690 if (name != NULL) {
691 // if name was passed in newOptions, push up
692 CFDictionarySetValue(newDict, kSCPropUserDefinedName, name);
693 } else {
694 name = CFDictionaryGetValue(newDict, kSCPropUserDefinedName);
695 if (name != NULL) {
696 CFMutableDictionaryRef newPPPEntity;
697
698 // if name in parent, push into entity
699 newPPPEntity = CFDictionaryCreateMutableCopy(NULL, 0, newOptions);
700 CFDictionarySetValue(newPPPEntity, kSCPropUserDefinedName, name);
701 CFDictionarySetValue(newDict, interfaceType, newPPPEntity);
702 CFRelease(newPPPEntity);
703 }
704 }
705 }
706 } else {
707 CFDictionaryRemoveValue(newDict, interfaceType);
708 }
709 }
710
711 return newDict;
712 }
713
714
715 Boolean
716 SCUserPreferencesSetInterfaceConfiguration(SCUserPreferencesRef userPreferences,
717 SCNetworkInterfaceRef interface,
718 CFDictionaryRef newOptions)
719 {
720 CFStringRef defaultType;
721 Boolean ok;
722 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
723
724 if (!isA_SCUserPreferences(userPreferences)) {
725 _SCErrorSet(kSCStatusInvalidArgument);
726 return FALSE;
727 }
728
729 if (!isA_SCNetworkInterface(interface)) {
730 _SCErrorSet(kSCStatusInvalidArgument);
731 return FALSE;
732 }
733
734 // get InterfaceType
735 defaultType = __SCNetworkInterfaceGetDefaultConfigurationType(interface);
736 if (defaultType == NULL) {
737 _SCErrorSet(kSCStatusInvalidArgument);
738 return FALSE;
739 }
740
741 // set new interface entity for SCUserPreferences
742 ok = processPreferences(userPrivate->serviceID,
743 setInterfaceConfigurationCallout,
744 (void *)userPrivate->prefsID,
745 (void *)defaultType,
746 (void *)newOptions);
747
748 return ok;
749 }
750
751
752 CFDictionaryRef
753 SCUserPreferencesCopyExtendedInterfaceConfiguration(SCUserPreferencesRef userPreferences,
754 SCNetworkInterfaceRef interface,
755 CFStringRef extendedType)
756 {
757 CFDictionaryRef entity = NULL;
758 Boolean ok;
759 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
760
761 if (!isA_SCUserPreferences(userPreferences)) {
762 _SCErrorSet(kSCStatusInvalidArgument);
763 return NULL;
764 }
765
766 if (!isA_SCNetworkInterface(interface)) {
767 _SCErrorSet(kSCStatusInvalidArgument);
768 return NULL;
769 }
770
771 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, FALSE)) {
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 *)extendedType,
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 Boolean
794 SCUserPreferencesSetExtendedInterfaceConfiguration(SCUserPreferencesRef userPreferences,
795 SCNetworkInterfaceRef interface,
796 CFStringRef extendedType,
797 CFDictionaryRef newOptions)
798 {
799 Boolean ok;
800 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
801
802 if (!isA_SCUserPreferences(userPreferences)) {
803 _SCErrorSet(kSCStatusInvalidArgument);
804 return FALSE;
805 }
806
807 if (!isA_SCNetworkInterface(interface)) {
808 _SCErrorSet(kSCStatusInvalidArgument);
809 return FALSE;
810 }
811
812 if (!__SCNetworkInterfaceIsValidExtendedConfigurationType(interface, extendedType, FALSE)) {
813 _SCErrorSet(kSCStatusInvalidArgument);
814 return FALSE;
815 }
816
817 // set new interface entity for SCUserPreferences
818 ok = processPreferences(userPrivate->serviceID,
819 setInterfaceConfigurationCallout,
820 (void *)userPrivate->prefsID,
821 (void *)extendedType,
822 (void *)newOptions);
823
824 return ok;
825 }
826
827
828 #pragma mark -
829 #pragma mark SCNetworkConnection + SCUserPreferences SPIs
830
831
832 static CFDictionaryRef
833 copyAllCallout(CFStringRef serviceID,
834 CFDictionaryRef current,
835 void *context1,
836 void *context2,
837 void *context3)
838 {
839 CFMutableArrayRef *prefs = (CFMutableArrayRef *)context3;
840 CFStringRef prefsID;
841 SCUserPreferencesPrivateRef userPrivate;
842
843 if (current == NULL) {
844 // we have nothing to "add"
845 return NULL;
846 }
847
848 prefsID = CFDictionaryGetValue(current, USER_PREFERENCES_ID);
849 if (!isA_CFString(prefsID)) {
850 // if no unique ID
851 goto done;
852 }
853
854 userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, prefsID);
855 if (userPrivate != NULL) {
856 if (*prefs == NULL) {
857 *prefs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
858 }
859 CFArrayAppendValue(*prefs, (SCUserPreferencesRef)userPrivate);
860 CFRelease(userPrivate);
861 }
862
863 done :
864
865 return CFRetain(current);
866 }
867
868
869 CFArrayRef /* of SCUserPreferencesRef's */
870 SCNetworkConnectionCopyAllUserPreferences(SCNetworkConnectionRef connection)
871 {
872 Boolean ok;
873 CFMutableArrayRef prefs = NULL;
874 CFStringRef serviceID;
875
876 // get serviceID
877 serviceID = SCNetworkConnectionCopyServiceID(connection);
878
879 // collect SCUserPreferences
880 ok = processPreferences(serviceID,
881 copyAllCallout,
882 NULL,
883 NULL,
884 (void *)&prefs);
885 if (!ok) {
886 if (prefs != NULL) {
887 CFRelease(prefs);
888 prefs = NULL;
889 }
890 }
891
892 CFRelease(serviceID);
893 return prefs;
894 }
895
896
897 static CFDictionaryRef
898 copyCurrentCallout(CFStringRef serviceID,
899 CFDictionaryRef current,
900 void *context1,
901 void *context2,
902 void *context3)
903 {
904 CFBooleanRef isDefault;
905 CFStringRef prefsID;
906 SCUserPreferencesPrivateRef *userPrivate = (SCUserPreferencesPrivateRef *)context3;
907
908 if (current == NULL) {
909 // we have nothing to "add"
910 return NULL;
911 }
912
913 prefsID = CFDictionaryGetValue(current, USER_PREFERENCES_ID);
914 if (!isA_CFString(prefsID)) {
915 // if no unique ID
916 goto done;
917 }
918
919 isDefault = CFDictionaryGetValue(current, USER_PREFERENCES_DEFAULT);
920 if (!isA_CFBoolean(isDefault) || !CFBooleanGetValue(isDefault)) {
921 // if not the default configuration
922 goto done;
923 }
924
925 *userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, prefsID);
926
927 done :
928
929 return CFRetain(current);
930 }
931
932
933 SCUserPreferencesRef
934 SCNetworkConnectionCopyCurrentUserPreferences(SCNetworkConnectionRef connection)
935 {
936 SCUserPreferencesRef current = NULL;
937 Boolean ok;
938 CFStringRef serviceID;
939
940 // get serviceID
941 serviceID = SCNetworkConnectionCopyServiceID(connection);
942
943 // collect SCUserPreferences
944 ok = processPreferences(serviceID,
945 copyCurrentCallout,
946 NULL,
947 NULL,
948 (void *)&current);
949 if (!ok) {
950 if (current != NULL) {
951 CFRelease(current);
952 current = NULL;
953 }
954 }
955
956 CFRelease(serviceID);
957 return current;
958 }
959
960
961 static CFDictionaryRef
962 createCallout(CFStringRef serviceID,
963 CFDictionaryRef current,
964 void *context1,
965 void *context2,
966 void *context3)
967 {
968 CFMutableDictionaryRef newDict;
969 CFStringRef newPrefsID = (CFStringRef)context1;
970
971 if (current != NULL) {
972 // don't change existing entries
973 return CFRetain(current);
974 }
975
976 newDict = CFDictionaryCreateMutable(NULL,
977 0,
978 &kCFTypeDictionaryKeyCallBacks,
979 &kCFTypeDictionaryValueCallBacks);
980 CFDictionarySetValue(newDict, USER_PREFERENCES_ID, newPrefsID);
981 return newDict;
982 }
983
984
985 SCUserPreferencesRef
986 SCNetworkConnectionCreateUserPreferences(SCNetworkConnectionRef connection)
987 {
988 CFStringRef newPrefsID;
989 CFStringRef serviceID;
990 SCUserPreferencesPrivateRef userPrivate;
991 CFUUIDRef uuid;
992
993 // get serviceID
994 serviceID = SCNetworkConnectionCopyServiceID(connection);
995
996 // allocate a new user preferences ID
997 uuid = CFUUIDCreate(NULL);
998 newPrefsID = CFUUIDCreateString(NULL, uuid);
999 CFRelease(uuid);
1000
1001 userPrivate = __SCUserPreferencesCreatePrivate(NULL, serviceID, newPrefsID);
1002 if (userPrivate != NULL) {
1003 (void) processPreferences(serviceID,
1004 createCallout,
1005 (void *)newPrefsID,
1006 NULL,
1007 NULL);
1008 }
1009
1010 CFRelease(newPrefsID);
1011 CFRelease(serviceID);
1012 return (SCUserPreferencesRef)userPrivate;
1013 }
1014
1015
1016 #ifdef NOTNOW
1017 Boolean
1018 SCNetworkConnectionSelectService(CFDictionaryRef selectionOptions,
1019 SCNetworkServiceRef *service,
1020 SCUserPreferencesRef *userPreferences)
1021 {
1022 return FALSE;
1023 }
1024 #endif // NOTNOW
1025
1026
1027 static void
1028 update_PPP_entity(SCUserPreferencesRef userPreferences, CFDictionaryRef *userOptions)
1029 {
1030 CFStringRef encryption;
1031 CFDictionaryRef entity;
1032 CFStringRef keychainID;
1033
1034 entity = CFDictionaryGetValue(*userOptions, kSCEntNetPPP);
1035 if (!isA_CFDictionary(entity)) {
1036 return;
1037 }
1038
1039 encryption = CFDictionaryGetValue(entity, kSCPropNetPPPAuthPasswordEncryption);
1040 if (encryption == NULL) {
1041 // provide default encryption method
1042 encryption = kSCValNetPPPAuthPasswordEncryptionKeychain;
1043 }
1044
1045 if (!isA_CFString(encryption) ||
1046 !CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
1047 return;
1048 }
1049
1050 keychainID = CFDictionaryGetValue(entity, kSCPropNetPPPAuthPassword);
1051 if (isA_CFString(keychainID)) {
1052 // if password is keychain ID
1053 } else if (isA_CFData(keychainID) &&
1054 ((CFDataGetLength((CFDataRef)keychainID) % sizeof(UniChar)) == 0)) {
1055 // if inline password
1056 return;
1057 } else {
1058 keychainID = SCUserPreferencesGetUniqueID(userPreferences);
1059 }
1060
1061 if (_SCSecKeychainPasswordItemExists(NULL, keychainID)) {
1062 CFMutableDictionaryRef new_entity;
1063 CFMutableDictionaryRef new_options;
1064
1065 // access PPP password from system keychain
1066 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
1067
1068 CFDictionarySetValue(new_entity,
1069 kSCPropNetPPPAuthPassword,
1070 keychainID);
1071 CFDictionarySetValue(new_entity,
1072 kSCPropNetPPPAuthPasswordEncryption,
1073 kSCValNetPPPAuthPasswordEncryptionKeychain);
1074
1075 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
1076 CFDictionarySetValue(new_options, kSCEntNetPPP, new_entity);
1077 CFRelease(new_entity);
1078
1079 CFRelease(*userOptions);
1080 *userOptions = new_options;
1081 }
1082
1083 return;
1084 }
1085
1086
1087 static void
1088 update_IPSec_entity(SCUserPreferencesRef userPreferences, CFDictionaryRef *userOptions)
1089 {
1090 CFStringRef encryption;
1091 CFDictionaryRef entity;
1092 SecKeychainRef keychain = NULL;
1093 CFStringRef keychainID;
1094 CFStringRef method;
1095 CFDataRef sharedSecret;
1096
1097 entity = CFDictionaryGetValue(*userOptions, kSCEntNetIPSec);
1098 if (!isA_CFDictionary(entity)) {
1099 return;
1100 }
1101
1102 method = CFDictionaryGetValue(entity, kSCPropNetIPSecAuthenticationMethod);
1103 if (!isA_CFString(method) ||
1104 !CFEqual(method, kSCValNetIPSecAuthenticationMethodSharedSecret)) {
1105 return;
1106 }
1107
1108 encryption = CFDictionaryGetValue(entity, kSCPropNetIPSecSharedSecretEncryption);
1109 if (encryption == NULL) {
1110 // provide default encryption method
1111 encryption = kSCValNetIPSecSharedSecretEncryptionKeychain;
1112 }
1113
1114 if (!isA_CFString(encryption) ||
1115 !CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
1116 return;
1117 }
1118
1119 keychainID = CFDictionaryGetValue(entity, kSCPropNetIPSecSharedSecret);
1120 if (isA_CFString(keychainID)) {
1121 // if shared secret is keychain ID
1122 CFRetain(keychainID);
1123 } else if (isA_CFData(keychainID) &&
1124 ((CFDataGetLength((CFDataRef)keychainID) % sizeof(UniChar)) == 0)) {
1125 // if inline shared secret
1126 return;
1127 } else {
1128 CFStringRef unique_id;
1129
1130 unique_id = SCUserPreferencesGetUniqueID(userPreferences);
1131 keychainID = (CFStringRef)CFStringCreateMutableCopy(NULL, 0, unique_id);
1132 CFStringAppend((CFMutableStringRef)keychainID, CFSTR(".SS"));
1133 }
1134
1135 sharedSecret = _SCSecKeychainPasswordItemCopy(NULL, keychainID);
1136 if (sharedSecret != NULL) {
1137 CFMutableDictionaryRef new_entity;
1138 CFMutableDictionaryRef new_options;
1139 CFStringRef password;
1140
1141 // pass SharedSecret from user keychain
1142 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
1143
1144 password = CFStringCreateWithBytes(NULL,
1145 CFDataGetBytePtr(sharedSecret),
1146 CFDataGetLength(sharedSecret),
1147 kCFStringEncodingUTF8,
1148 FALSE);
1149 CFRelease(sharedSecret);
1150 CFDictionarySetValue(new_entity,
1151 kSCPropNetIPSecSharedSecret,
1152 password);
1153 CFRelease(password);
1154 CFDictionaryRemoveValue(new_entity,
1155 kSCPropNetIPSecSharedSecretEncryption);
1156
1157 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
1158 CFDictionarySetValue(new_options, kSCEntNetIPSec, new_entity);
1159 CFRelease(new_entity);
1160
1161 CFRelease(*userOptions);
1162 *userOptions = new_options;
1163 goto done;
1164 }
1165
1166 keychain = _SCSecKeychainCopySystemKeychain();
1167 if (keychain == NULL) {
1168 goto done;
1169 }
1170
1171 if (_SCSecKeychainPasswordItemExists(keychain, keychainID)) {
1172 CFMutableDictionaryRef new_entity;
1173 CFMutableDictionaryRef new_options;
1174
1175 // access SharedSecret from system keychain
1176 new_entity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
1177
1178 CFDictionarySetValue(new_entity,
1179 kSCPropNetIPSecSharedSecret,
1180 keychainID);
1181 CFDictionarySetValue(new_entity,
1182 kSCPropNetIPSecSharedSecretEncryption,
1183 kSCValNetIPSecSharedSecretEncryptionKeychain);
1184
1185 new_options = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
1186 CFDictionarySetValue(new_options, kSCEntNetIPSec, new_entity);
1187 CFRelease(new_entity);
1188
1189 CFRelease(*userOptions);
1190 *userOptions = new_options;
1191 }
1192
1193 done :
1194
1195 if (keychain != NULL) CFRelease(keychain);
1196 CFRelease(keychainID);
1197 return;
1198 }
1199
1200
1201 static CFDictionaryRef
1202 copyOptionsCallout(CFStringRef serviceID,
1203 CFDictionaryRef current,
1204 void *context1,
1205 void *context2,
1206 void *context3)
1207 {
1208 CFStringRef matchID = (CFStringRef)context1;
1209 CFMutableDictionaryRef *userOptions = (CFMutableDictionaryRef *)context3;
1210
1211 if (current == NULL) {
1212 // we have nothing to "add"
1213 return NULL;
1214 }
1215
1216 if (isMatchingPrefsID(current, matchID)) {
1217 // if we match, return options dictionary
1218 if (*userOptions != NULL) CFRelease(*userOptions);
1219 *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, current);
1220 CFDictionaryRemoveValue(*userOptions, USER_PREFERENCES_ID);
1221 CFDictionaryRemoveValue(*userOptions, USER_PREFERENCES_DEFAULT);
1222 }
1223
1224 return CFRetain(current);
1225 }
1226
1227
1228 Boolean
1229 SCNetworkConnectionStartWithUserPreferences(SCNetworkConnectionRef connection,
1230 SCUserPreferencesRef userPreferences,
1231 Boolean linger)
1232 {
1233 Boolean ok;
1234 CFDictionaryRef userOptions = NULL;
1235 SCUserPreferencesPrivateRef userPrivate = (SCUserPreferencesPrivateRef)userPreferences;
1236
1237 if (!isA_SCUserPreferences(userPreferences)) {
1238 _SCErrorSet(kSCStatusInvalidArgument);
1239 return FALSE;
1240 }
1241
1242 (void) processPreferences(userPrivate->serviceID,
1243 copyOptionsCallout,
1244 (void *)userPrivate->prefsID,
1245 NULL,
1246 &userOptions);
1247
1248 /*
1249 * For some legacy preferences, some of the user options
1250 * were missing yet handled by the APIs. Make sure that
1251 * everything still works!
1252 */
1253 if (userOptions != NULL) {
1254 update_PPP_entity (userPreferences, &userOptions);
1255 update_IPSec_entity(userPreferences, &userOptions);
1256 }
1257
1258 ok = SCNetworkConnectionStart(connection, userOptions, linger);
1259
1260 if (userOptions != NULL) {
1261 CFRelease(userOptions);
1262 }
1263
1264 return ok;
1265 }
1266
1267
1268 #pragma mark -
1269 #pragma mark SCUserPreferences + SCNetworkInterface Password SPIs
1270
1271
1272 static CFStringRef
1273 getUserPasswordID(CFDictionaryRef config, SCUserPreferencesRef userPreferences)
1274 {
1275 CFStringRef unique_id = NULL;
1276
1277 if (config != NULL) {
1278 CFStringRef encryption;
1279
1280 encryption = CFDictionaryGetValue(config, kSCPropNetPPPAuthPasswordEncryption);
1281 if (isA_CFString(encryption) &&
1282 CFEqual(encryption, kSCValNetPPPAuthPasswordEncryptionKeychain)) {
1283 unique_id = CFDictionaryGetValue(config, kSCPropNetPPPAuthPassword);
1284 }
1285 }
1286 if (unique_id == NULL) {
1287 unique_id = SCUserPreferencesGetUniqueID(userPreferences);
1288 }
1289
1290 return unique_id;
1291 }
1292
1293
1294 static CFStringRef
1295 copyUserSharedSecretID(CFDictionaryRef config, SCUserPreferencesRef userPreferences)
1296 {
1297 CFMutableStringRef sharedSecret = NULL;
1298
1299 if (config != NULL) {
1300 CFStringRef encryption;
1301
1302 encryption = CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecretEncryption);
1303 if (isA_CFString(encryption) &&
1304 CFEqual(encryption, kSCValNetIPSecSharedSecretEncryptionKeychain)) {
1305 sharedSecret = (CFMutableStringRef)CFDictionaryGetValue(config, kSCPropNetIPSecSharedSecret);
1306 if (sharedSecret != NULL) {
1307 CFRetain(sharedSecret);
1308 }
1309 }
1310 }
1311
1312 if (sharedSecret == NULL) {
1313 CFStringRef unique_id;
1314
1315 unique_id = getUserPasswordID(config, userPreferences);
1316 sharedSecret = CFStringCreateMutableCopy(NULL, 0, unique_id);
1317 CFStringAppend(sharedSecret, CFSTR(".SS"));
1318 }
1319
1320 return sharedSecret;
1321 }
1322
1323
1324 static Boolean
1325 checkUserPreferencesPassword(SCUserPreferencesRef userPreferences,
1326 SCNetworkInterfaceRef interface,
1327 SCNetworkInterfacePasswordType passwordType)
1328 {
1329 if (!isA_SCUserPreferences(userPreferences)) {
1330 _SCErrorSet(kSCStatusInvalidArgument);
1331 return FALSE;
1332 }
1333
1334 if (!isA_SCNetworkInterface(interface)) {
1335 _SCErrorSet(kSCStatusInvalidArgument);
1336 return FALSE;
1337 }
1338
1339 switch (passwordType) {
1340 case kSCNetworkInterfacePasswordTypePPP : {
1341 CFStringRef interfaceType;
1342
1343 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1344 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
1345 _SCErrorSet(kSCStatusInvalidArgument);
1346 return FALSE;
1347 }
1348 break;
1349 }
1350
1351 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1352 CFStringRef interfaceType;
1353
1354 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1355 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
1356 _SCErrorSet(kSCStatusInvalidArgument);
1357 return FALSE;
1358 }
1359
1360 interface = SCNetworkInterfaceGetInterface(interface);
1361 if (interface == NULL) {
1362 _SCErrorSet(kSCStatusInvalidArgument);
1363 return FALSE;
1364 }
1365
1366 interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
1367 if (!CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
1368 _SCErrorSet(kSCStatusInvalidArgument);
1369 return FALSE;
1370 }
1371 break;
1372 }
1373
1374 case kSCNetworkInterfacePasswordTypeEAPOL : {
1375 _SCErrorSet(kSCStatusInvalidArgument);
1376 return FALSE;
1377 }
1378
1379 default :
1380 break;
1381 }
1382
1383 return TRUE;
1384 }
1385
1386
1387 Boolean
1388 SCUserPreferencesCheckInterfacePassword(SCUserPreferencesRef userPreferences,
1389 SCNetworkInterfaceRef interface,
1390 SCNetworkInterfacePasswordType passwordType)
1391 {
1392 Boolean exists = FALSE;
1393
1394 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1395 return FALSE;
1396 }
1397
1398 switch (passwordType) {
1399 case kSCNetworkInterfacePasswordTypePPP : {
1400 CFDictionaryRef config;
1401 CFStringRef unique_id;
1402
1403 // get configuration
1404 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1405
1406 // get userPreferences ID
1407 unique_id = getUserPasswordID(config, userPreferences);
1408
1409 // check
1410 exists = __extract_password(NULL,
1411 config,
1412 kSCPropNetPPPAuthPassword,
1413 kSCPropNetPPPAuthPasswordEncryption,
1414 kSCValNetPPPAuthPasswordEncryptionKeychain,
1415 unique_id,
1416 NULL);
1417
1418 if (config != NULL) CFRelease(config);
1419 break;
1420 }
1421
1422 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1423 CFDictionaryRef config;
1424 CFStringRef shared_id;
1425
1426 // get configuration
1427 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
1428 interface,
1429 kSCEntNetIPSec);
1430
1431 // get sharedSecret ID
1432 shared_id = copyUserSharedSecretID(config, userPreferences);
1433
1434 // check
1435 exists = __extract_password(NULL,
1436 config,
1437 kSCPropNetIPSecSharedSecret,
1438 kSCPropNetIPSecSharedSecretEncryption,
1439 kSCValNetIPSecSharedSecretEncryptionKeychain,
1440 shared_id,
1441 NULL);
1442
1443 if (config != NULL) CFRelease(config);
1444 CFRelease(shared_id);
1445 break;
1446 }
1447
1448 default :
1449 _SCErrorSet(kSCStatusInvalidArgument);
1450 return FALSE;
1451 }
1452
1453 return exists;
1454 }
1455
1456
1457 CFDataRef
1458 SCUserPreferencesCopyInterfacePassword(SCUserPreferencesRef userPreferences,
1459 SCNetworkInterfaceRef interface,
1460 SCNetworkInterfacePasswordType passwordType)
1461 {
1462 CFDataRef password = NULL;
1463
1464 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1465 return FALSE;
1466 }
1467
1468 switch (passwordType) {
1469 case kSCNetworkInterfacePasswordTypePPP : {
1470 CFDictionaryRef config;
1471 CFStringRef unique_id;
1472
1473 // get configuration
1474 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1475
1476 // get userPreferences ID
1477 unique_id = getUserPasswordID(config, userPreferences);
1478
1479 // extract
1480 (void) __extract_password(NULL,
1481 config,
1482 kSCPropNetPPPAuthPassword,
1483 kSCPropNetPPPAuthPasswordEncryption,
1484 kSCValNetPPPAuthPasswordEncryptionKeychain,
1485 unique_id,
1486 &password);
1487
1488 if (config != NULL) CFRelease(config);
1489 break;
1490 }
1491
1492 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1493 CFDictionaryRef config;
1494 CFStringRef shared_id;
1495
1496 // get configuration
1497 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
1498 interface,
1499 kSCEntNetIPSec);
1500
1501 // get sharedSecret ID
1502 shared_id = copyUserSharedSecretID(config, userPreferences);
1503
1504 // extract
1505 (void) __extract_password(NULL,
1506 config,
1507 kSCPropNetIPSecSharedSecret,
1508 kSCPropNetIPSecSharedSecretEncryption,
1509 kSCValNetIPSecSharedSecretEncryptionKeychain,
1510 shared_id,
1511 &password);
1512
1513 if (config != NULL) CFRelease(config);
1514 CFRelease(shared_id);
1515 break;
1516 }
1517
1518 default :
1519 _SCErrorSet(kSCStatusInvalidArgument);
1520 return NULL;
1521 }
1522
1523 return password;
1524 }
1525
1526
1527 Boolean
1528 SCUserPreferencesRemoveInterfacePassword(SCUserPreferencesRef userPreferences,
1529 SCNetworkInterfaceRef interface,
1530 SCNetworkInterfacePasswordType passwordType)
1531 {
1532 Boolean ok = FALSE;
1533
1534 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1535 return FALSE;
1536 }
1537
1538 switch (passwordType) {
1539 case kSCNetworkInterfacePasswordTypePPP : {
1540 CFDictionaryRef config;
1541 CFStringRef unique_id;
1542
1543 // get configuration
1544 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1545
1546 // get userPreferences ID
1547 unique_id = getUserPasswordID(config, userPreferences);
1548
1549 // remove password
1550 ok = _SCSecKeychainPasswordItemRemove(NULL, unique_id);
1551 if (ok) {
1552 CFDictionaryRef config;
1553 CFMutableDictionaryRef newConfig;
1554
1555 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1556 if (config != NULL) {
1557 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
1558 CFDictionaryRemoveValue(newConfig, kSCPropNetPPPAuthPassword);
1559 CFDictionaryRemoveValue(newConfig, kSCPropNetPPPAuthPasswordEncryption);
1560 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
1561 CFRelease(newConfig);
1562 }
1563 }
1564 break;
1565 }
1566
1567 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1568 CFDictionaryRef config;
1569 CFStringRef shared_id;
1570
1571 // get configuration
1572 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
1573 interface,
1574 kSCEntNetIPSec);
1575
1576 // get sharedSecret ID
1577 shared_id = copyUserSharedSecretID(config, userPreferences);
1578
1579 // remove password
1580 ok = _SCSecKeychainPasswordItemRemove(NULL, shared_id);
1581 if (ok) {
1582 CFMutableDictionaryRef newConfig;
1583
1584 if (config != NULL) {
1585 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
1586 CFDictionaryRemoveValue(newConfig, kSCPropNetIPSecSharedSecret);
1587 CFDictionaryRemoveValue(newConfig, kSCPropNetIPSecSharedSecretEncryption);
1588 ok = SCUserPreferencesSetExtendedInterfaceConfiguration(userPreferences,
1589 interface,
1590 kSCEntNetIPSec,
1591 newConfig);
1592 CFRelease(newConfig);
1593 }
1594 }
1595
1596 if (config != NULL) CFRelease(config);
1597 CFRelease(shared_id);
1598 break;
1599 }
1600
1601 default :
1602 _SCErrorSet(kSCStatusInvalidArgument);
1603 return FALSE;
1604 }
1605
1606 return ok;
1607 }
1608
1609
1610 Boolean
1611 SCUserPreferencesSetInterfacePassword(SCUserPreferencesRef userPreferences,
1612 SCNetworkInterfaceRef interface,
1613 SCNetworkInterfacePasswordType passwordType,
1614 CFDataRef password,
1615 CFDictionaryRef options)
1616 {
1617 CFStringRef account = NULL;
1618 CFBundleRef bundle;
1619 CFDictionaryRef config;
1620 CFStringRef description = NULL;
1621 CFStringRef label = NULL;
1622 Boolean ok = FALSE;
1623
1624 if (!checkUserPreferencesPassword(userPreferences, interface, passwordType)) {
1625 return FALSE;
1626 }
1627
1628 bundle = _SC_CFBundleGet();
1629
1630 switch (passwordType) {
1631 case kSCNetworkInterfacePasswordTypePPP : {
1632 CFStringRef unique_id;
1633
1634 // get configuration
1635 config = SCUserPreferencesCopyInterfaceConfiguration(userPreferences, interface);
1636
1637 // get userPreferences ID
1638 unique_id = getUserPasswordID(config, userPreferences);
1639
1640 // User prefs auth name --> keychain "Account"
1641 if (config != NULL) {
1642 account = CFDictionaryGetValue(config, kSCPropNetPPPAuthName);
1643 }
1644
1645 // User prefs "name" --> keychain "Name"
1646 label = SCUserPreferencesCopyName(userPreferences);
1647
1648 // "PPP Password" --> keychain "Kind"
1649 if (bundle != NULL) {
1650 description = CFBundleCopyLocalizedString(bundle,
1651 CFSTR("KEYCHAIN_PPP_PASSWORD"),
1652 CFSTR("PPP Password"),
1653 NULL);
1654 }
1655
1656 // store password
1657 ok = _SCSecKeychainPasswordItemSet(NULL,
1658 unique_id,
1659 (label != NULL) ? label : CFSTR("PPP"),
1660 (description != NULL) ? description : CFSTR("PPP Password"),
1661 account,
1662 password,
1663 options);
1664 if (ok) {
1665 CFMutableDictionaryRef newConfig;
1666
1667 if (config != NULL) {
1668 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
1669 } else {
1670 newConfig = CFDictionaryCreateMutable(NULL,
1671 0,
1672 &kCFTypeDictionaryKeyCallBacks,
1673 &kCFTypeDictionaryValueCallBacks);
1674 }
1675 CFDictionarySetValue(newConfig,
1676 kSCPropNetPPPAuthPassword,
1677 unique_id);
1678 CFDictionarySetValue(newConfig,
1679 kSCPropNetPPPAuthPasswordEncryption,
1680 kSCValNetPPPAuthPasswordEncryptionKeychain);
1681 ok = SCUserPreferencesSetInterfaceConfiguration(userPreferences, interface, newConfig);
1682 CFRelease(newConfig);
1683 }
1684
1685 if (config != NULL) CFRelease(config);
1686 if (description != NULL) CFRelease(description);
1687 if (label != NULL) CFRelease(label);
1688 break;
1689 }
1690
1691 case kSCNetworkInterfacePasswordTypeIPSecSharedSecret : {
1692 CFStringRef shared_id;
1693
1694 // get configuration
1695 config = SCUserPreferencesCopyExtendedInterfaceConfiguration(userPreferences,
1696 interface,
1697 kSCEntNetIPSec);
1698
1699 // get sharedSecret ID
1700 shared_id = copyUserSharedSecretID(config, userPreferences);
1701
1702 // User prefs "name" --> keychain "Name"
1703 label = SCUserPreferencesCopyName(userPreferences);
1704
1705 // "IPSec Shared Secret" --> keychain "Kind"
1706 if (bundle != NULL) {
1707 description = CFBundleCopyLocalizedString(bundle,
1708 CFSTR("KEYCHAIN_IPSEC_SHARED_SECRET"),
1709 CFSTR("IPSec Shared Secret"),
1710 NULL);
1711 }
1712
1713 // set password
1714 ok = _SCSecKeychainPasswordItemSet(NULL,
1715 shared_id,
1716 (label != NULL) ? label : CFSTR("PPP"),
1717 (description != NULL) ? description : CFSTR("IPSec Shared Secret"),
1718 NULL,
1719 password,
1720 options);
1721 if (ok) {
1722 CFMutableDictionaryRef newConfig = NULL;
1723
1724 if (config != NULL) {
1725 newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
1726 } else {
1727 newConfig = CFDictionaryCreateMutable(NULL,
1728 0,
1729 &kCFTypeDictionaryKeyCallBacks,
1730 &kCFTypeDictionaryValueCallBacks);
1731 }
1732 CFDictionarySetValue(newConfig,
1733 kSCPropNetIPSecSharedSecret,
1734 shared_id);
1735 CFDictionarySetValue(newConfig,
1736 kSCPropNetIPSecSharedSecretEncryption,
1737 kSCValNetIPSecSharedSecretEncryptionKeychain);
1738 ok = SCUserPreferencesSetExtendedInterfaceConfiguration(userPreferences,
1739 interface,
1740 kSCEntNetIPSec,
1741 newConfig);
1742 CFRelease(newConfig);
1743 }
1744
1745 if (config != NULL) CFRelease(config);
1746 if (description != NULL) CFRelease(description);
1747 if (label != NULL) CFRelease(label);
1748 CFRelease(shared_id);
1749 break;
1750 }
1751
1752 default :
1753 _SCErrorSet(kSCStatusInvalidArgument);
1754 return FALSE;
1755 }
1756
1757 return ok;
1758 }