]> git.saurik.com Git - apple/configd.git/blame - scselect.tproj/scselect.c
configd-802.20.7.tar.gz
[apple/configd.git] / scselect.tproj / scselect.c
CommitLineData
5958d7c0 1/*
9de8ab86 2 * Copyright (c) 2000-2009, 2011, 2012, 2014, 2015 Apple Inc. All rights reserved.
5958d7c0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
9de8ab86 5 *
009ee3c6
A
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.
9de8ab86 12 *
009ee3c6
A
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
5958d7c0
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
009ee3c6
A
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.
9de8ab86 20 *
5958d7c0
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
0fae82ee
A
24/*
25 * Modification History
26 *
4c5e92e2
A
27 * January 15, 2004 Allan Nathanson <ajn@apple.com>
28 * - limit location changes to "root" (uid==0), users who are
29 * a member of group "admin", and processses which have access
30 * to a local graphics console.
31 *
0fae82ee
A
32 * June 1, 2001 Allan Nathanson <ajn@apple.com>
33 * - public API conversion
34 *
35 * January 1, 2001 Allan Nathanson <ajn@apple.com>
36 * - initial revision
37 */
38
009ee3c6 39#include <getopt.h>
5958d7c0 40#include <unistd.h>
009ee3c6 41#include <sysexits.h>
4c5e92e2
A
42#include <sys/param.h>
43#include <sys/types.h>
4c5e92e2 44#include <sys/stat.h>
edebe297 45#include <dlfcn.h>
4c5e92e2 46#include <grp.h>
5958d7c0 47
0fae82ee
A
48#include <SystemConfiguration/SystemConfiguration.h>
49#include <SystemConfiguration/SCPrivate.h>
50
a40a14f8 51#if !TARGET_OS_IPHONE
5e9ce69e 52#include <Security/Authorization.h>
a40a14f8 53#endif /* !TARGET_OS_IPHONE */
4c5e92e2 54
5958d7c0 55
dbf6a266 56static Boolean apply = TRUE;
5958d7c0
A
57
58
dbf6a266 59static const struct option longopts[] = {
009ee3c6
A
60// { "debug", no_argument, 0, 'd' },
61// { "verbose", no_argument, 0, 'v' },
62// { "do-not-apply", no_argument, 0, 'n' },
63 { "help", no_argument, 0, '?' },
64 { 0, 0, 0, 0 }
65};
66
67
4c5e92e2 68static void
5958d7c0
A
69usage(const char *command)
70{
0fae82ee 71 SCPrint(TRUE, stderr, CFSTR("usage: %s [-n] new-set-name\n"), command);
009ee3c6 72 exit (EX_USAGE);
5958d7c0
A
73}
74
75
76int
77main(int argc, char **argv)
78{
79 const char *command = argv[0];
80 extern int optind;
81 int opt;
82 CFStringRef current = NULL;
83 int currentMatched = 0;
84 CFStringRef newSet = NULL; /* set key */
85 CFStringRef newSetUDN = NULL; /* user defined name */
86 CFStringRef prefix;
dbf6a266 87 SCPreferencesRef prefs;
5958d7c0
A
88 CFDictionaryRef sets;
89 CFIndex nSets;
a5f60add
A
90 const void **setKeys = NULL;
91 const void **setVals = NULL;
5958d7c0
A
92 CFIndex i;
93
5e9ce69e
A
94#if !TARGET_OS_IPHONE
95 AuthorizationRef authorization = NULL;
96 AuthorizationFlags flags = kAuthorizationFlagDefaults;
97 CFMutableDictionaryRef options;
98 OSStatus status;
99#endif // !TARGET_OS_IPHONE
100
5958d7c0
A
101 /* process any arguments */
102
17d3ee29 103 while ((opt = getopt_long(argc, argv, "dvn", longopts, NULL)) != -1) {
5958d7c0 104 switch(opt) {
17d3ee29
A
105 case 'd':
106 _sc_debug = TRUE;
107 _sc_log = FALSE; /* enable framework logging */
108 break;
109 case 'v':
110 _sc_verbose = TRUE;
111 break;
112 case 'n':
113 apply = FALSE;
114 break;
115 case '?':
116 default :
117 usage(command);
118 }
5958d7c0
A
119 }
120 argc -= optind;
121 argv += optind;
122
123 prefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("/%@/"), kSCPrefSets);
124
17d3ee29
A
125 if (argc == 1) {
126 newSet = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
5958d7c0 127
17d3ee29
A
128 /* check if a full path to the new "set" was specified */
129 if ((CFStringGetLength(newSet) > 0) && CFStringHasPrefix(newSet, prefix)) {
130 CFRange range;
131 CFMutableStringRef str;
5958d7c0 132
17d3ee29
A
133 str = CFStringCreateMutableCopy(NULL, 0, newSet);
134 CFRelease(newSet);
5958d7c0 135
17d3ee29
A
136 CFStringDelete(str, CFRangeMake(0, CFStringGetLength(prefix)));
137 newSet = CFStringCreateCopy(NULL, newSet);
138 CFRelease(str);
5958d7c0 139
17d3ee29
A
140 range = CFStringFind(newSet, CFSTR("/"), 0);
141 if (range.location != kCFNotFound) {
9de8ab86 142 SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available\n"), newSet);
17d3ee29
A
143 exit (1);
144 }
5958d7c0 145 }
17d3ee29
A
146 } else {
147 newSet = CFRetain(CFSTR(""));
148 }
5958d7c0 149
5e9ce69e
A
150#if !TARGET_OS_IPHONE
151 status = AuthorizationCreate(NULL,
152 kAuthorizationEmptyEnvironment,
153 flags,
154 &authorization);
155 if (status != errAuthorizationSuccess) {
156 SCPrint(TRUE,
157 stderr,
158 CFSTR("AuthorizationCreate() failed: status = %d\n"),
78403150 159 (int)status);
5e9ce69e
A
160 exit (1);
161 }
17d3ee29 162
5e9ce69e
A
163 options = CFDictionaryCreateMutable(NULL,
164 0,
165 &kCFTypeDictionaryKeyCallBacks,
166 &kCFTypeDictionaryValueCallBacks);
167 CFDictionarySetValue(options, kSCPreferencesOptionChangeNetworkSet, kCFBooleanTrue);
168 prefs = SCPreferencesCreateWithOptions(NULL, CFSTR("scselect"), NULL, authorization, options);
169 CFRelease(options);
17d3ee29
A
170 if (prefs == NULL) {
171 SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
172 exit (1);
5958d7c0 173 }
5e9ce69e
A
174#else // !TARGET_OS_IPHONE
175 prefs = SCPreferencesCreate(NULL, CFSTR("scselect"), NULL);
176 if (prefs == NULL) {
177 SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
178 exit (1);
179 }
180#endif // !TARGET_OS_IPHONE
5958d7c0 181
dbf6a266
A
182 sets = SCPreferencesGetValue(prefs, kSCPrefSets);
183 if (sets == NULL) {
184 SCPrint(TRUE, stderr, CFSTR("No network sets defined.\n"));
5958d7c0
A
185 exit (1);
186 }
187
dbf6a266
A
188 current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
189 if (current != NULL) {
0fae82ee
A
190 if (CFStringHasPrefix(current, prefix)) {
191 CFMutableStringRef tmp;
192
193 tmp = CFStringCreateMutableCopy(NULL, 0, current);
194 CFStringDelete(tmp, CFRangeMake(0, CFStringGetLength(prefix)));
195 current = tmp;
196 } else {
a40a14f8 197 CFRetain(current);
0fae82ee
A
198 currentMatched = -1; /* not prefixed */
199 }
200 } else {
a40a14f8 201 current = CFRetain(CFSTR(""));
0fae82ee 202 currentMatched = -2; /* not defined */
5958d7c0
A
203 }
204
205 nSets = CFDictionaryGetCount(sets);
a5f60add
A
206 if (nSets > 0) {
207 setKeys = CFAllocatorAllocate(NULL, nSets * sizeof(CFStringRef), 0);
208 setVals = CFAllocatorAllocate(NULL, nSets * sizeof(CFDictionaryRef), 0);
209 CFDictionaryGetKeysAndValues(sets, setKeys, setVals);
210 }
5958d7c0
A
211
212 /* check for set with matching name */
009ee3c6 213 for (i = 0; i < nSets; i++) {
5958d7c0
A
214 CFStringRef key = (CFStringRef) setKeys[i];
215 CFDictionaryRef dict = (CFDictionaryRef)setVals[i];
216
217 if ((currentMatched >= 0) && CFEqual(key, current)) {
218 currentMatched++;
219 }
220
221 if (CFEqual(newSet, key)) {
222 newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName);
dbf6a266 223 if (newSetUDN != NULL) CFRetain(newSetUDN);
5958d7c0
A
224 goto found;
225 }
226 }
227
228 /* check for set with matching user-defined name */
009ee3c6 229 for (i = 0; i < nSets; i++) {
5958d7c0
A
230 CFStringRef key = (CFStringRef) setKeys[i];
231 CFDictionaryRef dict = (CFDictionaryRef)setVals[i];
232
233 newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName);
234 if ((newSetUDN != NULL) && CFEqual(newSet, newSetUDN)) {
235 CFRelease(newSet);
236 newSet = CFRetain(key);
237 CFRetain(newSetUDN);
5958d7c0
A
238 goto found;
239 }
240 }
241
009ee3c6 242 if (argc == 1) {
6bb65964
A
243 SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available.\n"), newSet);
244 exit(1);
5958d7c0
A
245 }
246
6bb65964 247 SCPrint(TRUE, stdout,
0fae82ee
A
248 CFSTR("Defined sets include:%s\n"),
249 (currentMatched > 0) ? " (* == current set)" : "");
5958d7c0 250
009ee3c6 251 for (i = 0; i < nSets; i++) {
5958d7c0
A
252 CFStringRef key = (CFStringRef) setKeys[i];
253 CFDictionaryRef dict = (CFDictionaryRef)setVals[i];
254 CFStringRef udn = CFDictionaryGetValue(dict, kSCPropUserDefinedName);
255
6bb65964 256 SCPrint(TRUE, stdout,
0fae82ee 257 CFSTR(" %s %@\t(%@)\n"),
5958d7c0
A
258 ((currentMatched > 0) && CFEqual(key, current)) ? "*" : " ",
259 key,
260 udn ? udn : CFSTR(""));
261 }
262
263 switch (currentMatched) {
264 case -2 :
6bb65964 265 SCPrint(TRUE, stdout, CFSTR("\nCurrent set not defined.\n"));
5958d7c0
A
266 break;
267 case -1 :
6bb65964 268 SCPrint(TRUE, stdout, CFSTR("\nCurrent set \"%@\" may not be valid\n"), current);
5958d7c0
A
269 break;
270 case 0 :
6bb65964 271 SCPrint(TRUE, stdout, CFSTR("\nCurrent set \"%@\" not valid\n"), current);
5958d7c0
A
272 break;
273 default :
274 break;
275 }
276
5e9ce69e 277 CFRelease(prefix);
6bb65964 278 exit (0);
5958d7c0
A
279
280 found :
281
a40a14f8
A
282 CFRelease(current);
283 current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet);
284
9de8ab86 285 SCPreferencesSetValue(prefs, kSCPrefCurrentSet, current);
5958d7c0 286
dbf6a266 287 if (!SCPreferencesCommitChanges(prefs)) {
5e9ce69e
A
288 int sc_status = SCError();
289
290 if (sc_status == kSCStatusAccessError) {
291 SCPrint(TRUE, stderr,
292 CFSTR("Only local console users and administrators can change locations\n"));
293 exit (EX_NOPERM);
294 } else {
295 SCPrint(TRUE, stderr,
296 CFSTR("SCPreferencesCommitChanges() failed: %s\n"),
297 SCErrorString(sc_status));
298 exit (1);
299 }
5958d7c0
A
300 }
301
302 if (apply) {
dbf6a266 303 if (!SCPreferencesApplyChanges(prefs)) {
5e9ce69e
A
304 SCPrint(TRUE, stderr,
305 CFSTR("SCPreferencesApplyChanges() failed %s\n"),
306 SCErrorString(SCError()));
5958d7c0
A
307 exit (1);
308 }
309 }
310
0fae82ee
A
311 SCPrint(TRUE, stdout,
312 CFSTR("%@ updated to %@ (%@)\n"),
5958d7c0
A
313 kSCPrefCurrentSet,
314 newSet,
315 newSetUDN ? newSetUDN : CFSTR(""));
316
a40a14f8
A
317 CFRelease(current);
318 CFRelease(newSet);
319 if (newSetUDN != NULL) CFRelease(newSetUDN);
320 CFRelease(prefix);
321 CFRelease(prefs);
322
5e9ce69e
A
323#if !TARGET_OS_IPHONE
324 AuthorizationFree(authorization, kAuthorizationFlagDefaults);
325// AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
326#endif /* !TARGET_OS_IPHONE */
327
5958d7c0
A
328 exit (0);
329 return 0;
330}