2 * Copyright (c) 2004-2007, 2009, 2010 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 27, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <SystemConfiguration/SystemConfiguration.h>
34 #include <SystemConfiguration/SCValidation.h>
35 #include <SystemConfiguration/SCPrivate.h>
37 #include <sys/ioctl.h>
41 __private_extern__ CFDictionaryRef
42 __getPrefsConfiguration(SCPreferencesRef prefs
, CFStringRef path
)
44 CFDictionaryRef config
;
47 config
= SCPreferencesPathGetValue(prefs
, path
);
49 n
= isA_CFDictionary(config
) ? CFDictionaryGetCount(config
) : 0;
52 // ignore empty configuration entities
56 if (CFDictionaryContainsKey(config
, kSCResvInactive
)) {
57 // ignore [effectively] empty configuration entities
69 __private_extern__ Boolean
70 __setPrefsConfiguration(SCPreferencesRef prefs
,
72 CFDictionaryRef config
,
75 CFMutableDictionaryRef newConfig
= NULL
;
78 if ((config
!= NULL
) && !isA_CFDictionary(config
)) {
79 _SCErrorSet(kSCStatusInvalidArgument
);
84 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
88 CFDictionaryRef curConfig
;
91 newConfig
= CFDictionaryCreateMutable(NULL
,
93 &kCFTypeDictionaryKeyCallBacks
,
94 &kCFTypeDictionaryValueCallBacks
);
97 curConfig
= SCPreferencesPathGetValue(prefs
, path
);
98 if (isA_CFDictionary(curConfig
) && CFDictionaryContainsKey(curConfig
, kSCResvInactive
)) {
99 // if currently disabled
100 CFDictionarySetValue(newConfig
, kSCResvInactive
, kCFBooleanTrue
);
102 // if currently enabled
103 CFDictionaryRemoveValue(newConfig
, kSCResvInactive
);
107 // set new configuration
108 if (newConfig
!= NULL
) {
109 // if new configuration (or we are preserving a disabled state)
110 ok
= SCPreferencesPathSetValue(prefs
, path
, newConfig
);
111 CFRelease(newConfig
);
113 ok
= SCPreferencesPathRemoveValue(prefs
, path
);
114 if (!ok
&& (SCError() == kSCStatusNoKey
)) {
123 __private_extern__ Boolean
124 __getPrefsEnabled(SCPreferencesRef prefs
, CFStringRef path
)
126 CFDictionaryRef config
;
128 config
= SCPreferencesPathGetValue(prefs
, path
);
129 if (isA_CFDictionary(config
) && CFDictionaryContainsKey(config
, kSCResvInactive
)) {
137 __private_extern__ Boolean
138 __setPrefsEnabled(SCPreferencesRef prefs
,
142 CFDictionaryRef curConfig
;
143 CFMutableDictionaryRef newConfig
= NULL
;
146 // preserve current configuration
147 curConfig
= SCPreferencesPathGetValue(prefs
, path
);
148 if (curConfig
!= NULL
) {
149 if (!isA_CFDictionary(curConfig
)) {
150 _SCErrorSet(kSCStatusFailed
);
153 newConfig
= CFDictionaryCreateMutableCopy(NULL
, 0, curConfig
);
157 CFDictionaryRemoveValue(newConfig
, kSCResvInactive
);
160 CFDictionarySetValue(newConfig
, kSCResvInactive
, kCFBooleanTrue
);
165 newConfig
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
166 CFDictionarySetValue(newConfig
, kSCResvInactive
, kCFBooleanTrue
);
170 // set new configuration
171 if (newConfig
!= NULL
) {
172 // if updated configuration (or we are establishing as disabled)
173 ok
= SCPreferencesPathSetValue(prefs
, path
, newConfig
);
174 CFRelease(newConfig
);
176 ok
= SCPreferencesPathRemoveValue(prefs
, path
);
177 if (!ok
&& (SCError() == kSCStatusNoKey
)) {
186 static CFDictionaryRef
190 CFErrorRef error
= NULL
;
192 CFDictionaryRef templates
;
194 CFDataRef xmlTemplates
= NULL
;
196 bundle
= _SC_CFBundleGet();
197 if (bundle
== NULL
) {
201 url
= CFBundleCopyResourceURL(bundle
, CFSTR("NetworkConfiguration"), CFSTR("plist"), NULL
);
206 ok
= CFURLCreateDataAndPropertiesFromResource(NULL
, url
, &xmlTemplates
, NULL
, NULL
, NULL
);
208 if (!ok
|| (xmlTemplates
== NULL
)) {
212 // convert the XML data into a property list
213 templates
= CFPropertyListCreateWithData(NULL
, xmlTemplates
, kCFPropertyListImmutable
, NULL
, &error
);
214 CFRelease(xmlTemplates
);
215 if (templates
== NULL
) {
217 SCLog(TRUE
, LOG_DEBUG
, CFSTR("could not load SCNetworkConfiguration templates: %@"), error
);
223 if (!isA_CFDictionary(templates
)) {
224 CFRelease(templates
);
232 __private_extern__ CFDictionaryRef
233 __copyInterfaceTemplate(CFStringRef interfaceType
,
234 CFStringRef childInterfaceType
)
236 CFDictionaryRef interface
= NULL
;
237 CFDictionaryRef interfaces
;
238 CFDictionaryRef templates
;
240 templates
= __copyTemplates();
241 if (templates
== NULL
) {
245 interfaces
= CFDictionaryGetValue(templates
, CFSTR("Interface"));
246 if (!isA_CFDictionary(interfaces
)) {
247 CFRelease(templates
);
251 if (childInterfaceType
== NULL
) {
252 interface
= CFDictionaryGetValue(interfaces
, interfaceType
);
254 CFStringRef expandedType
;
256 if (CFStringFind(childInterfaceType
, CFSTR("."), 0).location
!= kCFNotFound
) {
258 childInterfaceType
= CFSTR("*");
261 expandedType
= CFStringCreateWithFormat(NULL
,
266 interface
= CFDictionaryGetValue(interfaces
, expandedType
);
267 CFRelease(expandedType
);
270 if (isA_CFDictionary(interface
) && (CFDictionaryGetCount(interface
) > 0)) {
276 CFRelease(templates
);
282 __private_extern__ CFDictionaryRef
283 __copyProtocolTemplate(CFStringRef interfaceType
,
284 CFStringRef childInterfaceType
,
285 CFStringRef protocolType
)
287 CFDictionaryRef interface
= NULL
;
288 CFDictionaryRef protocol
= NULL
;
289 CFDictionaryRef protocols
;
290 CFDictionaryRef templates
;
292 templates
= __copyTemplates();
293 if (templates
== NULL
) {
297 protocols
= CFDictionaryGetValue(templates
, CFSTR("Protocol"));
298 if (!isA_CFDictionary(protocols
)) {
299 CFRelease(templates
);
303 if (childInterfaceType
== NULL
) {
304 interface
= CFDictionaryGetValue(protocols
, interfaceType
);
306 CFStringRef expandedType
;
308 if (CFStringFind(childInterfaceType
, CFSTR("."), 0).location
!= kCFNotFound
) {
310 childInterfaceType
= CFSTR("*");
313 expandedType
= CFStringCreateWithFormat(NULL
,
318 interface
= CFDictionaryGetValue(protocols
, expandedType
);
319 CFRelease(expandedType
);
322 if (isA_CFDictionary(interface
)) {
323 protocol
= CFDictionaryGetValue(interface
, protocolType
);
324 if (isA_CFDictionary(protocol
)) {
331 CFRelease(templates
);
337 __private_extern__ Boolean
338 __createInterface(int s
, CFStringRef interface
)
342 bzero(&ifr
, sizeof(ifr
));
343 (void) _SC_cfstring_to_cstring(interface
,
345 sizeof(ifr
.ifr_name
),
346 kCFStringEncodingASCII
);
348 if (ioctl(s
, SIOCIFCREATE
, &ifr
) == -1) {
351 CFSTR("could not create interface \"%@\": %s"),
361 __private_extern__ Boolean
362 __destroyInterface(int s
, CFStringRef interface
)
366 bzero(&ifr
, sizeof(ifr
));
367 (void) _SC_cfstring_to_cstring(interface
,
369 sizeof(ifr
.ifr_name
),
370 kCFStringEncodingASCII
);
372 if (ioctl(s
, SIOCIFDESTROY
, &ifr
) == -1) {
375 CFSTR("could not destroy interface \"%@\": %s"),
386 * For rdar://problem/4685223
388 * To keep MoreSCF happy we need to ensure that the first "Set" and
389 * "NetworkService" have a [less than] unique identifier that can
390 * be parsed as a numeric string.
392 * Note: this backwards compatibility code must be enabled using the
395 * sudo defaults write \
396 * /Library/Preferences/SystemConfiguration/preferences \
402 __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(SCPreferencesRef prefs
, CFStringRef prefix
)
404 static int hack
= -1;
405 CFStringRef path
= NULL
;
410 enable
= SCPreferencesGetValue(prefs
, CFSTR("MoreSCF"));
411 hack
= (isA_CFBoolean(enable
) && CFBooleanGetValue(enable
)) ? 1 : 0;
415 CFDictionaryRef dict
;
418 path
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@/%@"), prefix
, CFSTR("0"));
419 dict
= SCPreferencesPathGetValue(prefs
, path
);
421 // if path "0" exists
426 // unique child with path "0" does not exist, create
427 dict
= CFDictionaryCreate(NULL
,
429 &kCFTypeDictionaryKeyCallBacks
,
430 &kCFTypeDictionaryValueCallBacks
);
431 ok
= SCPreferencesPathSetValue(prefs
, path
, dict
);
445 __copy_legacy_password(CFTypeRef password
)
447 if (password
== NULL
) {
451 if (isA_CFData(password
)) {
454 n
= CFDataGetLength(password
);
455 if ((n
% sizeof(UniChar
)) == 0) {
456 CFStringEncoding encoding
;
460 encoding
= (*(CFDataGetBytePtr(password
) + 1) == 0x00) ? kCFStringEncodingUTF16LE
: kCFStringEncodingUTF16BE
;
461 #else // __LITTLE_ENDIAN__
462 encoding
= (*(CFDataGetBytePtr(password
) ) == 0x00) ? kCFStringEncodingUTF16BE
: kCFStringEncodingUTF16LE
;
464 str
= CFStringCreateWithBytes(NULL
,
465 (const UInt8
*)CFDataGetBytePtr(password
),
469 password
= CFStringCreateExternalRepresentation(NULL
,
471 kCFStringEncodingUTF8
,
477 } else if (isA_CFString(password
) && (CFStringGetLength(password
) > 0)) {
478 // convert password to CFData
479 password
= CFStringCreateExternalRepresentation(NULL
,
481 kCFStringEncodingUTF8
,
493 __extract_password(SCPreferencesRef prefs
,
494 CFDictionaryRef config
,
495 CFStringRef passwordKey
,
496 CFStringRef encryptionKey
,
497 CFStringRef encryptionKeyChainValue
,
498 CFStringRef unique_id
,
501 CFStringRef encryption
= NULL
;
502 Boolean exists
= FALSE
;
504 // check for keychain password
505 if (config
!= NULL
) {
506 encryption
= CFDictionaryGetValue(config
, encryptionKey
);
508 if ((encryption
== NULL
) ||
509 (isA_CFString(encryption
) &&
510 CFEqual(encryption
, encryptionKeyChainValue
))) {
512 if (password
!= NULL
) {
514 *password
= _SCPreferencesSystemKeychainPasswordItemCopy(prefs
, unique_id
);
516 *password
= _SCSecKeychainPasswordItemCopy(NULL
, unique_id
);
518 exists
= (*password
!= NULL
);
521 exists
= _SCPreferencesSystemKeychainPasswordItemExists(prefs
, unique_id
);
523 exists
= _SCSecKeychainPasswordItemExists(NULL
, unique_id
);
528 // as needed, check for in-line password
529 if (!exists
&& (encryption
== NULL
) && (config
!= NULL
)) {
530 CFDataRef inline_password
;
532 inline_password
= CFDictionaryGetValue(config
, passwordKey
);
533 inline_password
= __copy_legacy_password(inline_password
);
534 if (inline_password
!= NULL
) {
537 if (password
!= NULL
) {
538 *password
= inline_password
;
540 CFRelease(inline_password
);
551 __remove_password(SCPreferencesRef prefs
,
552 CFDictionaryRef config
,
553 CFStringRef passwordKey
,
554 CFStringRef encryptionKey
,
555 CFStringRef encryptionKeyChainValue
,
556 CFStringRef unique_id
,
557 CFDictionaryRef
*newConfig
)
559 CFStringRef encryption
= NULL
;
562 // check for keychain password
563 if (config
!= NULL
) {
564 encryption
= CFDictionaryGetValue(config
, encryptionKey
);
566 if ((encryption
== NULL
) ||
567 (isA_CFString(encryption
) &&
568 CFEqual(encryption
, encryptionKeyChainValue
))) {
569 // remove keychain password
571 ok
= _SCPreferencesSystemKeychainPasswordItemRemove(prefs
, unique_id
);
573 ok
= _SCSecKeychainPasswordItemRemove(NULL
, unique_id
);
577 // as needed, check if we have an in-line password that we can remove
578 if (!ok
&& (encryption
== NULL
) && (config
!= NULL
)) {
579 CFDataRef inline_password
;
581 inline_password
= CFDictionaryGetValue(config
, passwordKey
);
582 inline_password
= __copy_legacy_password(inline_password
);
583 if (inline_password
!= NULL
) {
584 CFRelease(inline_password
);
589 if (newConfig
!= NULL
) {
590 if (ok
&& (config
!= NULL
)) {
591 CFMutableDictionaryRef temp
;
593 temp
= CFDictionaryCreateMutableCopy(NULL
, 0, config
);
594 CFDictionaryRemoveValue(temp
, passwordKey
);
595 CFDictionaryRemoveValue(temp
, encryptionKey
);
596 *newConfig
= (CFDictionaryRef
)temp
;