2 * Copyright (c) 2003-2008, 2011-2013 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 29, 2003 Allan Nathanson <ajn@apple.com>
32 #include <sys/param.h>
33 #include <sys/types.h>
37 #include <SystemConfiguration/SCPreferencesSetSpecific.h>
39 #include <Security/Authorization.h>
40 #endif /* !TARGET_OS_IPHONE */
47 /* -------------------- */
52 __loadSecurity(void) {
53 static void *image
= NULL
;
55 const char *framework
= "/System/Library/Frameworks/Security.framework/Security";
57 const char *suffix
= getenv("DYLD_IMAGE_SUFFIX");
58 char path
[MAXPATHLEN
];
60 strlcpy(path
, framework
, sizeof(path
));
61 if (suffix
) strlcat(path
, suffix
, sizeof(path
));
62 if (0 <= stat(path
, &statbuf
)) {
63 image
= dlopen(path
, RTLD_LAZY
| RTLD_LOCAL
);
65 image
= dlopen(framework
, RTLD_LAZY
| RTLD_LOCAL
);
73 _AuthorizationCreate(const AuthorizationRights
*rights
, const AuthorizationEnvironment
*environment
, AuthorizationFlags flags
, AuthorizationRef
*authorization
)
75 #undef AuthorizationCreate
76 static typeof (AuthorizationCreate
) *dyfunc
= NULL
;
78 void *image
= __loadSecurity();
79 if (image
) dyfunc
= dlsym(image
, "AuthorizationCreate");
81 return dyfunc
? dyfunc(rights
, environment
, flags
, authorization
) : -1;
83 #define AuthorizationCreate _AuthorizationCreate
87 _AuthorizationFree(AuthorizationRef authorization
, AuthorizationFlags flags
)
89 #undef AuthorizationFree
90 static typeof (AuthorizationFree
) *dyfunc
= NULL
;
92 void *image
= __loadSecurity();
93 if (image
) dyfunc
= dlsym(image
, "AuthorizationFree");
95 return dyfunc
? dyfunc(authorization
, flags
) : -1;
97 #define AuthorizationFree _AuthorizationFree
100 /* -------------------- */
104 _prefs_AuthorizationCreate()
106 AuthorizationRef authorization
= NULL
;
108 if (getenv("SCPREFERENCES_USE_ENTITLEMENTS") != NULL
) {
109 authorization
= kSCPreferencesUseEntitlementAuthorization
;
111 AuthorizationFlags flags
= kAuthorizationFlagDefaults
;
114 status
= AuthorizationCreate(NULL
,
115 kAuthorizationEmptyEnvironment
,
118 if (status
!= errAuthorizationSuccess
) {
121 CFSTR("AuthorizationCreate() failed: status = %d\n"),
127 return authorization
;
133 _prefs_AuthorizationFree(AuthorizationRef authorization
)
135 if (authorization
!= kSCPreferencesUseEntitlementAuthorization
) {
136 AuthorizationFree(authorization
, kAuthorizationFlagDefaults
);
137 // AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
143 #endif /* !TARGET_OS_IPHONE */
145 /* -------------------- */
148 __private_extern__ Boolean _prefs_changed
= FALSE
;
153 _prefs_open(CFStringRef name
, CFStringRef prefsID
)
155 CFMutableDictionaryRef options
= NULL
;
156 Boolean useHelper
= FALSE
;
157 Boolean useOptions
= FALSE
;
159 authorization
= NULL
;
161 if (geteuid() != 0) {
162 // if we need to use a helper
165 #if !TARGET_OS_IPHONE
166 authorization
= _prefs_AuthorizationCreate();
168 authorization
= kSCPreferencesUseEntitlementAuthorization
;
169 #endif /* !TARGET_OS_IPHONE */
172 if (getenv("SCPREFERENCES_REMOVE_WHEN_EMPTY") != NULL
) {
173 // if we have options
176 if (options
== NULL
) {
177 options
= CFDictionaryCreateMutable(NULL
,
179 &kCFTypeDictionaryKeyCallBacks
,
180 &kCFTypeDictionaryValueCallBacks
);
182 CFDictionarySetValue(options
, kSCPreferencesOptionRemoveWhenEmpty
, kCFBooleanTrue
);
185 if (!useHelper
&& !useOptions
) {
186 // if no helper/options needed
187 prefs
= SCPreferencesCreate(NULL
, name
, prefsID
);
188 } else if (!useOptions
) {
189 // if no options needed
190 prefs
= SCPreferencesCreateWithAuthorization(NULL
, name
, prefsID
, authorization
);
192 prefs
= SCPreferencesCreateWithOptions(NULL
, name
, prefsID
, authorization
, options
);
200 _prefs_changed
= FALSE
;
209 if (!SCPreferencesCommitChanges(prefs
)) {
211 case kSCStatusAccessError
:
212 SCPrint(TRUE
, stderr
, CFSTR("Permission denied.\n"));
217 CFSTR("SCPreferencesCommitChanges() failed: %s\n"),
218 SCErrorString(SCError()));
224 _prefs_changed
= FALSE
;
226 if (!SCPreferencesApplyChanges(prefs
)) {
229 CFSTR("SCPreferencesApplyChanges() failed: %s\n"),
230 SCErrorString(SCError()));
245 _prefs_changed
= FALSE
;
248 if (authorization
!= NULL
) {
249 #if !TARGET_OS_IPHONE
250 _prefs_AuthorizationFree(authorization
);
251 #else /* !TARGET_OS_IPHONE */
252 // Uh...if authorization isn't NULL, something went horribly wrong.
253 #endif /* !TARGET_OS_IPHONE */
254 authorization
= NULL
;
263 _prefs_commitRequired(int argc
, char **argv
, const char *command
)
265 if (_prefs_changed
) {
266 if ((currentInput
!= NULL
) &&
267 isatty(fileno(currentInput
->fp
)) &&
268 ((argc
< 1) || (strcmp(argv
[0], "!") != 0))
270 SCPrint(TRUE
, stdout
,
271 CFSTR("preference changes have not been committed\n"
272 "use \"commit\" to save changes"));
273 if (command
!= NULL
) {
274 SCPrint(TRUE
, stdout
,
275 CFSTR(" or \"%s !\" to abandon changes"),
278 SCPrint(TRUE
, stdout
, CFSTR("\n"));
282 SCPrint(TRUE
, stdout
, CFSTR("preference changes abandoned\n"));
289 /* -------------------- */
293 get_ComputerName(int argc
, char **argv
)
295 CFStringEncoding encoding
;
296 CFStringRef hostname
;
298 hostname
= SCDynamicStoreCopyComputerName(NULL
, &encoding
);
299 if (hostname
== NULL
) {
300 int sc_status
= SCError();
303 case kSCStatusNoKey
:
306 CFSTR("ComputerName: not set\n"));
311 CFSTR("SCDynamicStoreCopyComputerName() failed: %s\n"),
312 SCErrorString(SCError()));
318 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), hostname
);
326 set_ComputerName(int argc
, char **argv
)
328 CFStringRef hostname
;
331 ok
= _prefs_open(CFSTR("scutil --set ComputerName"), NULL
);
335 CFSTR("Could not open prefs: %s\n"),
336 SCErrorString(SCError()));
341 CFStringEncoding old_encoding
;
342 CFStringRef old_hostname
;
344 old_hostname
= SCDynamicStoreCopyComputerName(NULL
, &old_encoding
);
345 hostname
= _copyStringFromSTDIN(CFSTR("ComputerName"), old_hostname
);
346 if (old_hostname
) CFRelease(old_hostname
);
348 hostname
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
351 ok
= SCPreferencesSetComputerName(prefs
, hostname
, kCFStringEncodingUTF8
);
352 if (hostname
!= NULL
) CFRelease(hostname
);
356 CFSTR("Could not open prefs: %s\n"),
357 SCErrorString(SCError()));
369 get_HostName(int argc
, char **argv
)
371 CFStringRef hostname
;
374 ok
= _prefs_open(CFSTR("scutil --get HostName"), NULL
);
378 CFSTR("SCPreferencesCreate() failed: %s\n"),
379 SCErrorString(SCError()));
383 hostname
= SCPreferencesGetHostName(prefs
);
384 if (hostname
== NULL
) {
385 int sc_status
= SCError();
388 case kSCStatusNoKey
:
391 CFSTR("HostName: not set\n"));
396 CFSTR("SCPreferencesGetHostName() failed: %s\n"),
397 SCErrorString(SCError()));
404 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), hostname
);
411 set_HostName(int argc
, char **argv
)
413 CFStringRef hostname
= NULL
;
416 ok
= _prefs_open(CFSTR("scutil --set HostName"), NULL
);
420 CFSTR("Could not open prefs: %s\n"),
421 SCErrorString(SCError()));
426 hostname
= _copyStringFromSTDIN(CFSTR("HostName"), SCPreferencesGetHostName(prefs
));
428 hostname
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
431 ok
= SCPreferencesSetHostName(prefs
, hostname
);
432 if (hostname
!= NULL
) CFRelease(hostname
);
436 CFSTR("SCPreferencesSetHostName() failed: %s\n"),
437 SCErrorString(SCError()));
449 get_LocalHostName(int argc
, char **argv
)
451 CFStringRef hostname
;
453 hostname
= SCDynamicStoreCopyLocalHostName(NULL
);
454 if (hostname
== NULL
) {
455 int sc_status
= SCError();
458 case kSCStatusNoKey
:
461 CFSTR("LocalHostName: not set\n"));
466 CFSTR("SCDynamicStoreCopyLocalHostName() failed: %s\n"),
467 SCErrorString(SCError()));
473 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), hostname
);
481 set_LocalHostName(int argc
, char **argv
)
483 CFStringRef hostname
= NULL
;
486 ok
= _prefs_open(CFSTR("scutil --set LocalHostName"), NULL
);
490 CFSTR("Could not open prefs: %s\n"),
491 SCErrorString(SCError()));
496 CFStringRef old_hostname
;
498 old_hostname
= SCDynamicStoreCopyLocalHostName(NULL
);
499 hostname
= _copyStringFromSTDIN(CFSTR("LocalHostName"), old_hostname
);
500 if (old_hostname
) CFRelease(old_hostname
);
502 hostname
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
505 ok
= SCPreferencesSetLocalHostName(prefs
, hostname
);
506 if (hostname
!= NULL
) CFRelease(hostname
);
510 CFSTR("SCPreferencesSetLocalHostName() failed: %s\n"),
511 SCErrorString(SCError()));
522 /* -------------------- */
525 typedef void (*pref_func
) (int argc
, char **argv
);
527 static const struct {
532 { "ComputerName", get_ComputerName
, set_ComputerName
},
533 { "HostName", get_HostName
, set_HostName
},
534 { "LocalHostName", get_LocalHostName
, set_LocalHostName
}
536 #define N_PREF_KEYS (sizeof(pref_keys) / sizeof(pref_keys[0]))
545 for (i
= 0; i
< (int)N_PREF_KEYS
; i
++) {
546 if (strcmp(pref
, pref_keys
[i
].pref
) == 0) {
557 do_getPref(char *pref
, int argc
, char **argv
)
564 (*pref_keys
[i
].get
)(argc
, argv
);
569 // Add support to parse out extended get
570 // ie. scutil --get <filename> <prefs path> <key>
572 do_prefs_open(argc
, argv
);
573 do_prefs_get(--argc
, ++argv
);
577 CFStringRef prefs_val
;
579 key
= CFStringCreateWithCString(NULL
, *(++argv
), kCFStringEncodingUTF8
);
580 prefs_val
= CFDictionaryGetValue(value
, key
);
583 if (prefs_val
!= NULL
) {
584 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), prefs_val
);
597 do_setPref(char *pref
, int argc
, char **argv
)
603 (*pref_keys
[i
].set
)(argc
, argv
);
609 /* -------------------- */
622 do_prefs_open(int argc
, char **argv
)
625 CFStringRef prefsID
= NULL
;
628 if (_prefs_commitRequired(argc
, argv
, "close")) {
632 do_prefs_close(0, NULL
);
636 prefsID
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
639 ok
= _prefs_open(CFSTR("scutil --prefs"), prefsID
);
640 if (prefsID
!= NULL
) CFRelease(prefsID
);
644 CFSTR("Could not open prefs: %s\n"),
645 SCErrorString(SCError()));
655 do_prefs_lock(int argc
, char **argv
)
657 Boolean wait
= (argc
> 0) ? TRUE
: FALSE
;
659 if (!SCPreferencesLock(prefs
, wait
)) {
660 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
670 do_prefs_unlock(int argc
, char **argv
)
672 if (!SCPreferencesUnlock(prefs
)) {
673 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
683 do_prefs_commit(int argc
, char **argv
)
685 if (!SCPreferencesCommitChanges(prefs
)) {
686 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
690 _prefs_changed
= FALSE
;
697 do_prefs_apply(int argc
, char **argv
)
699 if (!SCPreferencesApplyChanges(prefs
)) {
700 SCPrint(TRUE
, stdout
, CFSTR("%s\n"), SCErrorString(SCError()));
709 do_prefs_close(int argc
, char **argv
)
711 if (_prefs_commitRequired(argc
, argv
, "close")) {
722 do_prefs_quit(int argc
, char **argv
)
724 if (_prefs_commitRequired(argc
, argv
, "quit")) {
730 termRequested
= TRUE
;
737 do_prefs_synchronize(int argc
, char **argv
)
739 SCPreferencesSynchronize(prefs
);
744 static CFComparisonResult
745 sort_paths(const void *p1
, const void *p2
, void *context
) {
746 CFStringRef path1
= (CFStringRef
)p1
;
747 CFStringRef path2
= (CFStringRef
)p2
;
748 return CFStringCompare(path1
, path2
, 0);
754 do_prefs_list(int argc
, char **argv
)
758 CFMutableArrayRef paths
= NULL
;
760 CFDictionaryRef entity
;
762 prefix
= CFStringCreateWithCString(NULL
,
763 (argc
>= 1) ? argv
[0] : "/",
764 kCFStringEncodingUTF8
);
766 entity
= SCPreferencesPathGetValue(prefs
, prefix
);
767 if (entity
== NULL
) {
768 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
772 paths
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
774 n
= isA_CFDictionary(entity
) ? CFDictionaryGetCount(entity
) : 0;
780 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFStringRef
), 0);
781 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
782 CFDictionaryGetKeysAndValues(entity
, keys
, vals
);
783 for (i
= 0; i
< n
; i
++) {
784 if (isA_CFDictionary(vals
[i
])) {
785 CFArrayAppendValue(paths
, keys
[i
]);
788 CFAllocatorDeallocate(NULL
, keys
);
789 CFAllocatorDeallocate(NULL
, vals
);
792 n
= CFArrayGetCount(paths
);
793 CFArraySortValues(paths
,
799 for (i
= 0; i
< n
; i
++) {
802 CFSTR(" path [%d] = %@/%@\n"),
804 CFEqual(prefix
, CFSTR("/")) ? CFSTR("") : prefix
,
805 CFArrayGetValueAtIndex(paths
, i
));
808 SCPrint(TRUE
, stdout
, CFSTR(" no paths.\n"));
822 do_prefs_get(int argc
, char **argv
)
824 CFDictionaryRef dict
;
827 CFMutableDictionaryRef newDict
;
830 path
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
832 link
= SCPreferencesPathGetLink(prefs
, path
);
834 SCPrint(TRUE
, stdout
, CFSTR(" --> %@\n"), link
);
837 dict
= SCPreferencesPathGetValue(prefs
, path
);
840 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
844 newDict
= CFDictionaryCreateMutable(NULL
,
846 &kCFTypeDictionaryKeyCallBacks
,
847 &kCFTypeDictionaryValueCallBacks
);
849 // remove [path] children
850 n
= isA_CFDictionary(dict
) ? CFDictionaryGetCount(dict
) : 0;
856 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFStringRef
), 0);
857 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
858 CFDictionaryGetKeysAndValues(dict
, keys
, vals
);
859 for (i
= 0; i
< n
; i
++) {
860 if (!isA_CFDictionary(vals
[i
])) {
861 CFDictionaryAddValue(newDict
, keys
[i
], vals
[i
]);
864 CFAllocatorDeallocate(NULL
, keys
);
865 CFAllocatorDeallocate(NULL
, vals
);
869 CFRelease(value
); /* we have new information, release the old */
880 do_prefs_set(int argc
, char **argv
)
882 CFDictionaryRef dict
;
883 CFMutableDictionaryRef newDict
= NULL
;
886 path
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
887 newDict
= CFDictionaryCreateMutableCopy(NULL
, 0, value
);
889 dict
= SCPreferencesPathGetValue(prefs
, path
);
893 // retain [path] children
894 n
= CFDictionaryGetCount(dict
);
900 keys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFStringRef
), 0);
901 vals
= CFAllocatorAllocate(NULL
, n
* sizeof(CFPropertyListRef
), 0);
902 CFDictionaryGetKeysAndValues(dict
, keys
, vals
);
903 for (i
= 0; i
< n
; i
++) {
904 if (isA_CFDictionary(vals
[i
])) {
905 if (CFDictionaryContainsKey(newDict
, keys
[i
])) {
906 SCPrint(TRUE
, stdout
, CFSTR(" key %@ is already a path component and cannot be replaced\n"), keys
[i
]);
909 CFDictionaryAddValue(newDict
, keys
[i
], vals
[i
]);
912 CFAllocatorDeallocate(NULL
, keys
);
913 CFAllocatorDeallocate(NULL
, vals
);
915 } else if (SCError() == kSCStatusInvalidArgument
) {
916 SCPrint(TRUE
, stdout
, CFSTR(" a path component is not a dictionary\n"));
918 } else if (SCError() != kSCStatusNoKey
) {
919 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
928 link
= CFStringCreateWithCString(NULL
, argv
[1], kCFStringEncodingUTF8
);
929 ok
= SCPreferencesPathSetLink(prefs
, path
, link
);
932 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
937 if (!SCPreferencesPathSetValue(prefs
, path
, newDict
)) {
938 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
943 _prefs_changed
= TRUE
;
955 do_prefs_remove(int argc
, char **argv
)
959 path
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
961 if (!SCPreferencesPathRemoveValue(prefs
, path
)) {
962 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
966 _prefs_changed
= TRUE
;
974 /* -------------------- */
976 #include "IPMonitorControlPrefs.h"
980 do_log(char * log
, int argc
, char **argv
)
982 if (strcmp(log
, "IPMonitor")) {
986 printf("IPMonitor log is %s\n",
987 IPMonitorControlPrefsIsVerbose() ? "on" : "off");
990 Boolean verbose
= FALSE
;
992 if (strcasecmp(argv
[0], "on") == 0) {
995 else if (strcasecmp(argv
[0], "off") == 0) {
999 fprintf(stderr
, "%s invalid, must be 'on' or 'off'\n",
1003 if (IPMonitorControlPrefsSetVerbose(verbose
) == FALSE
) {
1004 fprintf(stderr
, "failed to set preferences\n");