]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDHostName.c
configd-1109.40.9.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCDHostName.c
1 /*
2 * Copyright (c) 2000-2008, 2011, 2013-2020 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 /*
25 * Modification History
26 *
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * January 8, 2001 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34
35 #include <CoreFoundation/CoreFoundation.h>
36 #include <CoreFoundation/CFStringDefaultEncoding.h> // for __CFStringGetUserDefaultEncoding
37 #include "SCPreferencesInternal.h"
38 #include "SCNetworkConfigurationInternal.h"
39 #include "dy_framework.h"
40
41
42 #ifndef __OPEN_SOURCE
43 #pragma mark Support
44
45
46 static Boolean
47 keepPrivate(void)
48 {
49 static Boolean keepPrivate = FALSE;
50 static dispatch_once_t once;
51
52 dispatch_once(&once, ^{
53 SecTaskRef current_task;
54
55 current_task = SecTaskCreateFromSelf(NULL);
56 if (current_task != NULL) {
57 CFBooleanRef entitlement;
58
59 entitlement = SecTaskCopyValueForEntitlement(current_task,
60 CFSTR("com.apple.security.on-demand-install-capable"),
61 NULL);
62 if (entitlement != NULL) {
63 if (isA_CFBoolean(entitlement)) {
64 keepPrivate = CFBooleanGetValue(entitlement);
65 }
66 CFRelease(entitlement);
67 }
68 CFRelease(current_task);
69 }
70 });
71
72 return keepPrivate;
73 }
74 #endif // __OPEN_SOURCE
75
76
77 #pragma mark ComputerName
78
79
80 static CFStringEncoding
81 getNameEncoding(CFDictionaryRef dict)
82 {
83 CFStringEncoding encoding;
84 CFNumberRef num;
85
86 if (!CFDictionaryGetValueIfPresent(dict,
87 kSCPropSystemComputerNameEncoding,
88 (const void **)&num) ||
89 !isA_CFNumber(num) ||
90 !CFNumberGetValue(num, kCFNumberSInt32Type, &encoding)) {
91 encoding = CFStringGetSystemEncoding();
92 }
93
94 return encoding;
95 }
96
97
98 CFStringRef
99 _SCPreferencesCopyComputerName(SCPreferencesRef prefs,
100 CFStringEncoding *nameEncoding)
101 {
102 CFDictionaryRef dict;
103 CFStringRef name = NULL;
104 CFStringRef path;
105 Boolean tempPrefs = FALSE;
106
107 if (prefs == NULL) {
108 prefs = SCPreferencesCreate(NULL, CFSTR("_SCPreferencesCopyComputerName"), NULL);
109 if (prefs == NULL) {
110 return NULL;
111 }
112 tempPrefs = TRUE;
113 }
114
115 path = CFStringCreateWithFormat(NULL,
116 NULL,
117 CFSTR("/%@/%@"),
118 kSCPrefSystem,
119 kSCCompSystem);
120 dict = SCPreferencesPathGetValue(prefs, path);
121 CFRelease(path);
122
123 if (dict != NULL) {
124 if (isA_CFDictionary(dict)) {
125 name = CFDictionaryGetValue(dict, kSCPropSystemComputerName);
126 name = isA_CFString(name);
127 if (name != NULL) {
128 CFRetain(name);
129 }
130 }
131
132 if (nameEncoding != NULL) {
133 *nameEncoding = getNameEncoding(dict);
134 }
135 }
136
137 if (tempPrefs) CFRelease(prefs);
138 _SCErrorSet(name != NULL ? kSCStatusOK : kSCStatusNoKey);
139 return name;
140 }
141
142
143 CFStringRef
144 SCDynamicStoreKeyCreateComputerName(CFAllocatorRef allocator)
145 {
146 return SCDynamicStoreKeyCreate(allocator,
147 CFSTR("%@/%@"),
148 kSCDynamicStoreDomainSetup,
149 kSCCompSystem);
150 }
151
152
153 CFStringRef
154 SCDynamicStoreCopyComputerName(SCDynamicStoreRef store,
155 CFStringEncoding *nameEncoding)
156 {
157 CFDictionaryRef dict = NULL;
158 CFStringRef key;
159 CFStringRef name = NULL;
160
161 #ifndef __OPEN_SOURCE
162 if (keepPrivate()) {
163 return NULL;
164 }
165 #endif // __OPEN_SOURCE
166
167 key = SCDynamicStoreKeyCreateComputerName(NULL);
168 dict = SCDynamicStoreCopyValue(store, key);
169 CFRelease(key);
170 if (dict == NULL) {
171 /*
172 * Let's try looking in the preferences.plist file until
173 * (a) we add an API to retrieve the name regardless of
174 * where it is stored and
175 * (b) this API is deprecated
176 */
177 name = _SCPreferencesCopyComputerName(NULL, nameEncoding);
178 goto done;
179 }
180 if (!isA_CFDictionary(dict)) {
181 _SCErrorSet(kSCStatusNoKey);
182 goto done;
183 }
184
185 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
186 if (name == NULL) {
187 _SCErrorSet(kSCStatusNoKey);
188 goto done;
189 }
190 CFRetain(name);
191
192 if (nameEncoding != NULL) {
193 *nameEncoding = getNameEncoding(dict);
194 }
195
196 _SCErrorSet(kSCStatusOK);
197
198 done :
199
200
201 if (dict != NULL) CFRelease(dict);
202 return name;
203 }
204
205
206 Boolean
207 SCPreferencesSetComputerName(SCPreferencesRef prefs,
208 CFStringRef name,
209 CFStringEncoding encoding)
210 {
211 CFDictionaryRef dict;
212 CFMutableDictionaryRef newDict;
213 CFNumberRef num;
214 Boolean ok;
215 CFStringRef path;
216
217 if (name != NULL) {
218 CFIndex len;
219
220 if (!isA_CFString(name)) {
221 _SCErrorSet(kSCStatusInvalidArgument);
222 return FALSE;
223 }
224
225 len = CFStringGetLength(name);
226 if (len == 0) {
227 name = NULL;
228 }
229 }
230
231 path = CFStringCreateWithFormat(NULL,
232 NULL,
233 CFSTR("/%@/%@"),
234 kSCPrefSystem,
235 kSCCompSystem);
236
237 dict = SCPreferencesPathGetValue(prefs, path);
238 if (dict != NULL) {
239 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
240 } else {
241 newDict = CFDictionaryCreateMutable(NULL,
242 0,
243 &kCFTypeDictionaryKeyCallBacks,
244 &kCFTypeDictionaryValueCallBacks);
245 }
246
247 if ((name != NULL) && (CFStringGetLength(name) > 0)) {
248 CFDictionarySetValue(newDict, kSCPropSystemComputerName, name);
249
250 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &encoding);
251 CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num);
252 CFRelease(num);
253
254 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerNameRegion);
255 if (encoding == kCFStringEncodingMacRoman) {
256 UInt32 userEncoding = 0;
257 UInt32 userRegion = 0;
258
259 __CFStringGetUserDefaultEncoding(&userEncoding, &userRegion);
260 if ((userEncoding == kCFStringEncodingMacRoman) && (userRegion != 0)) {
261 num = CFNumberCreate(NULL, kCFNumberSInt32Type, &userRegion);
262 CFDictionarySetValue(newDict, kSCPropSystemComputerNameRegion, num);
263 CFRelease(num);
264 }
265 }
266 } else {
267 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerName);
268 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerNameEncoding);
269 CFDictionaryRemoveValue(newDict, kSCPropSystemComputerNameRegion);
270 }
271
272 ok = __SCNetworkConfigurationSetValue(prefs, path, newDict, FALSE);
273 if (ok && __SCPreferencesUsingDefaultPrefs(prefs)) {
274 if (name != NULL) {
275 SC_log(LOG_NOTICE, "attempting to set the computer name to \"%@\"", name);
276 } else {
277 SC_log(LOG_NOTICE, "attempting to reset the computer name");
278 }
279 }
280
281 CFRelease(path);
282 CFRelease(newDict);
283
284 return ok;
285 }
286
287
288 #pragma mark -
289 #pragma mark HostName
290
291
292 CFStringRef
293 SCPreferencesGetHostName(SCPreferencesRef prefs)
294 {
295 CFDictionaryRef dict;
296 CFStringRef name;
297 CFStringRef path;
298
299 #ifndef __OPEN_SOURCE
300 if (keepPrivate()) {
301 return NULL;
302 }
303 #endif // __OPEN_SOURCE
304
305 path = CFStringCreateWithFormat(NULL,
306 NULL,
307 CFSTR("/%@/%@"),
308 kSCPrefSystem,
309 kSCCompSystem);
310 dict = SCPreferencesPathGetValue(prefs, path);
311 CFRelease(path);
312
313 if (!isA_CFDictionary(dict)) {
314 _SCErrorSet(kSCStatusNoKey);
315 return NULL;
316 }
317
318 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemHostName));
319 if (name == NULL) {
320 _SCErrorSet(kSCStatusNoKey);
321 return NULL;
322 }
323
324 return name;
325 }
326
327
328 Boolean
329 SCPreferencesSetHostName(SCPreferencesRef prefs,
330 CFStringRef name)
331 {
332 CFDictionaryRef dict;
333 CFMutableDictionaryRef newDict;
334 Boolean ok;
335 CFStringRef path;
336
337 if (name != NULL) {
338 CFIndex len;
339
340 if (!isA_CFString(name)) {
341 _SCErrorSet(kSCStatusInvalidArgument);
342 return FALSE;
343 }
344
345 len = CFStringGetLength(name);
346 if (len == 0) {
347 name = NULL;
348 }
349 }
350
351 path = CFStringCreateWithFormat(NULL,
352 NULL,
353 CFSTR("/%@/%@"),
354 kSCPrefSystem,
355 kSCCompSystem);
356
357 dict = SCPreferencesPathGetValue(prefs, path);
358 if (dict != NULL) {
359 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
360 } else {
361 newDict = CFDictionaryCreateMutable(NULL,
362 0,
363 &kCFTypeDictionaryKeyCallBacks,
364 &kCFTypeDictionaryValueCallBacks);
365 }
366
367 if (name != NULL) {
368 CFDictionarySetValue(newDict, kSCPropSystemHostName, name);
369 } else {
370 CFDictionaryRemoveValue(newDict, kSCPropSystemHostName);
371 }
372
373 ok = __SCNetworkConfigurationSetValue(prefs, path, newDict, FALSE);
374 if (ok && __SCPreferencesUsingDefaultPrefs(prefs)) {
375 if (name != NULL) {
376 SC_log(LOG_NOTICE, "attempting to set the host name to \"%@\"", name);
377 } else {
378 SC_log(LOG_NOTICE, "attempting to reset the host name");
379 }
380 }
381
382 CFRelease(path);
383 CFRelease(newDict);
384
385 return ok;
386 }
387
388
389 #pragma mark -
390 #pragma mark LocalHostName
391
392
393 CFStringRef
394 _SCPreferencesCopyLocalHostName(SCPreferencesRef prefs)
395 {
396 CFDictionaryRef dict;
397 CFStringRef name = NULL;
398 CFStringRef path;
399 Boolean tempPrefs = FALSE;
400
401 if (prefs == NULL) {
402 prefs = SCPreferencesCreate(NULL, CFSTR("_SCPreferencesCopyLocalHostName"), NULL);
403 if (prefs == NULL) {
404 return NULL;
405 }
406 tempPrefs = TRUE;
407 }
408
409 path = CFStringCreateWithFormat(NULL,
410 NULL,
411 CFSTR("/%@/%@/%@"),
412 kSCPrefSystem,
413 kSCCompNetwork,
414 kSCCompHostNames);
415 dict = SCPreferencesPathGetValue(prefs, path);
416 CFRelease(path);
417
418 if (dict != NULL) {
419 if (isA_CFDictionary(dict)) {
420 name = CFDictionaryGetValue(dict, kSCPropNetLocalHostName);
421 name = isA_CFString(name);
422 if (name != NULL) {
423 CFRetain(name);
424 }
425 }
426 }
427
428 if (tempPrefs) CFRelease(prefs);
429 _SCErrorSet(name != NULL ? kSCStatusOK : kSCStatusNoKey);
430 return name;
431 }
432
433
434 CFStringRef
435 SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator)
436 {
437 return SCDynamicStoreKeyCreate(allocator,
438 CFSTR("%@/%@/%@"),
439 kSCDynamicStoreDomainSetup,
440 kSCCompNetwork,
441 kSCCompHostNames);
442 }
443
444
445 CFStringRef
446 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
447 {
448 CFDictionaryRef dict = NULL;
449 CFStringRef key;
450 CFStringRef name = NULL;
451
452 #ifndef __OPEN_SOURCE
453 if (keepPrivate()) {
454 return NULL;
455 }
456 #endif // __OPEN_SOURCE
457
458 key = SCDynamicStoreKeyCreateHostNames(NULL);
459 dict = SCDynamicStoreCopyValue(store, key);
460 CFRelease(key);
461 if (dict == NULL) {
462 /*
463 * Let's try looking in the preferences.plist file until
464 * (a) we add an API to retrieve the name regardless of
465 * where it is stored and
466 * (b) this API is deprecated
467 */
468 name = _SCPreferencesCopyLocalHostName(NULL);
469 goto done;
470 }
471 if (!isA_CFDictionary(dict)) {
472 _SCErrorSet(kSCStatusNoKey);
473 goto done;
474 }
475
476 name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
477 if (name == NULL) {
478 _SCErrorSet(kSCStatusNoKey);
479 goto done;
480 }
481 CFRetain(name);
482
483 _SCErrorSet(kSCStatusOK);
484
485 done :
486
487
488 if (dict != NULL) CFRelease(dict);
489 return name;
490 }
491
492
493 Boolean
494 _SC_stringIsValidDNSName(const char *name)
495 {
496 size_t i;
497 size_t len = strlen(name);
498 char prev = '\0';
499 const char *scan;
500
501 if (len == 0) {
502 return FALSE;
503 }
504
505 for (scan = name, i = 0; i < len; i++, scan++) {
506 char ch = *scan;
507 char next = *(scan + 1);
508
509 if (prev == '.' || prev == '\0') {
510 if (isalnum(ch) == 0) {
511 /* a label must begin with a letter or digit */
512 return FALSE;
513 }
514 } else if (next == '\0' || next == '.') {
515 if (isalnum(ch) == 0) {
516 /* a label must end with a letter or digit */
517 return FALSE;
518 }
519 } else if (isalnum(ch) == 0) {
520 switch (ch) {
521 case '.':
522 /* a label separator */
523 break;
524 case '-':
525 /* hyphens are OK within a label */
526 break;
527 default:
528 /* an invalid character */
529 return FALSE;
530 break;
531 }
532 }
533 prev = ch;
534 }
535
536 return TRUE;
537 }
538
539
540 Boolean
541 _SC_CFStringIsValidDNSName(CFStringRef name)
542 {
543 Boolean clean = FALSE;
544 char *str = NULL;
545
546 if (!isA_CFString(name)) {
547 return FALSE;
548 }
549
550 str = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII);
551 if (str == NULL) {
552 return FALSE;
553 }
554
555 clean = _SC_stringIsValidDNSName(str);
556
557 if (str != NULL) CFAllocatorDeallocate(NULL, str);
558 return clean;
559 }
560
561
562 Boolean
563 SCPreferencesSetLocalHostName(SCPreferencesRef prefs,
564 CFStringRef name)
565 {
566 CFDictionaryRef dict;
567 CFMutableDictionaryRef newDict;
568 Boolean ok;
569 CFStringRef path;
570
571 if (name != NULL) {
572 CFIndex len;
573
574 if (!isA_CFString(name)) {
575 _SCErrorSet(kSCStatusInvalidArgument);
576 return FALSE;
577 }
578
579 len = CFStringGetLength(name);
580 if (len > 0) {
581 if (!_SC_CFStringIsValidDNSName(name)) {
582 _SCErrorSet(kSCStatusInvalidArgument);
583 return FALSE;
584 }
585
586 if (CFStringFindWithOptions(name, CFSTR("."), CFRangeMake(0, len), 0, NULL)) {
587 _SCErrorSet(kSCStatusInvalidArgument);
588 return FALSE;
589 }
590 } else {
591 name = NULL;
592 }
593 }
594
595 path = CFStringCreateWithFormat(NULL,
596 NULL,
597 CFSTR("/%@/%@/%@"),
598 kSCPrefSystem,
599 kSCCompNetwork,
600 kSCCompHostNames);
601
602 dict = SCPreferencesPathGetValue(prefs, path);
603 if (dict != NULL) {
604 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
605 } else {
606 newDict = CFDictionaryCreateMutable(NULL,
607 0,
608 &kCFTypeDictionaryKeyCallBacks,
609 &kCFTypeDictionaryValueCallBacks);
610 }
611
612 if (name != NULL) {
613 CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
614 } else {
615 CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
616 }
617
618 ok = __SCNetworkConfigurationSetValue(prefs, path, newDict, FALSE);
619 if (ok && __SCPreferencesUsingDefaultPrefs(prefs)) {
620 if (name != NULL) {
621 SC_log(LOG_NOTICE, "attempting to set the local host name to \"%@\"", name);
622 } else {
623 SC_log(LOG_NOTICE, "attempting to reset the local host name");
624 }
625 }
626
627 CFRelease(path);
628 CFRelease(newDict);
629
630 return ok;
631 }
632
633
634 Boolean
635 _SC_CFStringIsValidNetBIOSName(CFStringRef name)
636 {
637 if (!isA_CFString(name)) {
638 return FALSE;
639 }
640
641 if (CFStringGetLength(name) > 15) {
642 return FALSE;
643 }
644
645 return TRUE;
646 }