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