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