]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCNetworkSignature.c
configd-888.51.2.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCNetworkSignature.c
1 /*
2 * Copyright (c) 2006, 2008, 2009, 2011-2015 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 * SCNetworkSignature.c
26 * - implementation of SCNetworkSignatureRef API that allows access to
27 network identification information
28 *
29 */
30 /*
31 * Modification History
32 *
33 * November 6, 2006 Dieter Siegmund (dieter@apple.com)
34 * - initial revision
35 */
36
37
38 #include <netinet/in.h>
39 #include <CoreFoundation/CFDictionary.h>
40 #include <CoreFoundation/CFString.h>
41 #include <CoreFoundation/CFArray.h>
42 #include <CoreFoundation/CFRuntime.h>
43 #include <SystemConfiguration/SCDynamicStore.h>
44 #include <SystemConfiguration/SCValidation.h>
45 #include <SystemConfiguration/SCPrivate.h>
46 #include "SCNetworkSignature.h"
47 #include "SCNetworkSignaturePrivate.h"
48 #include <arpa/inet.h>
49 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <net/if.h>
52 #include <network/conninfo.h>
53
54 #pragma mark SCNetworkSignature Supporting APIs
55
56 static CFStringRef
57 create_global_state_v4_key(void)
58 {
59 return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
60 kSCDynamicStoreDomainState,
61 kSCEntNetIPv4);
62
63 }
64
65 static CFStringRef
66 create_global_setup_v4_key(void)
67 {
68 return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
69 kSCDynamicStoreDomainSetup,
70 kSCEntNetIPv4);
71 }
72
73 static CFStringRef
74 create_ipv4_services_pattern(void)
75 {
76 return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
77 kSCDynamicStoreDomainState,
78 kSCCompAnyRegex,
79 kSCEntNetIPv4);
80 }
81
82 static CFStringRef
83 create_ipv6_services_pattern(void)
84 {
85 return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
86 kSCDynamicStoreDomainState,
87 kSCCompAnyRegex,
88 kSCEntNetIPv6);
89 }
90
91 static CFDictionaryRef
92 copy_services_for_address_family(CFAllocatorRef alloc,
93 int af)
94 {
95 CFDictionaryRef info;
96 CFArrayRef patterns;
97 CFStringRef pattern;
98 CFStringRef prop;
99
100 prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6;
101 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
102 kSCDynamicStoreDomainState,
103 kSCCompAnyRegex,
104 prop);
105 patterns = CFArrayCreate(NULL,
106 (const void * *)&pattern, 1,
107 &kCFTypeArrayCallBacks);
108 CFRelease(pattern);
109 info = SCDynamicStoreCopyMultiple(NULL, NULL, patterns);
110 CFRelease(patterns);
111
112 return (info);
113 }
114
115
116 static CF_RETURNS_RETAINED CFStringRef
117 my_IPAddressToCFString(int af, const void * src_p)
118 {
119 char ntopbuf[INET6_ADDRSTRLEN];
120
121 if (inet_ntop(af, src_p, ntopbuf, sizeof(ntopbuf)) != NULL) {
122 return (CFStringCreateWithCString(NULL, ntopbuf,
123 kCFStringEncodingASCII));
124 }
125 return (NULL);
126 }
127
128 #pragma mark -
129
130
131 #pragma mark SCNetworkSignature APIs
132
133 CFStringRef
134 SCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc,
135 const struct sockaddr * addr)
136 {
137 CFStringRef ident = NULL;
138 CFDictionaryRef info = NULL;
139 CFStringRef global_state_v4_key = NULL;
140 CFDictionaryRef global_v4_state_dict = NULL;
141 CFArrayRef keys = NULL;
142 CFArrayRef patterns = NULL;
143 in_addr_t s_addr;
144 CFStringRef service = NULL;
145 CFDictionaryRef service_dict = NULL;
146 CFStringRef service_id = NULL;
147 struct sockaddr_in * sin_p;
148 CFStringRef v4_service_pattern = NULL;
149
150 /* only accept 0.0.0.0 (i.e. default) for now */
151 if (addr == NULL
152 || addr->sa_family != AF_INET
153 || addr->sa_len != sizeof(struct sockaddr_in)) {
154 _SCErrorSet(kSCStatusInvalidArgument);
155 goto done;
156 }
157
158 /* ALIGN: force alignment */
159 sin_p = (struct sockaddr_in *)(void *)addr;
160 bcopy(&sin_p->sin_addr.s_addr, &s_addr, sizeof(s_addr));
161 if (s_addr != 0) {
162 _SCErrorSet(kSCStatusInvalidArgument);
163 goto done;
164 }
165
166 global_state_v4_key = create_global_state_v4_key();
167 keys = CFArrayCreate(NULL, (const void * *)&global_state_v4_key,
168 1, &kCFTypeArrayCallBacks);
169
170 v4_service_pattern = create_ipv4_services_pattern();
171 patterns = CFArrayCreate(NULL, (const void * *)&v4_service_pattern, 1,
172 &kCFTypeArrayCallBacks);
173
174 info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
175
176 if (info == NULL
177 || CFDictionaryGetCount(info) == 0) {
178 goto done;
179 }
180
181 global_v4_state_dict = CFDictionaryGetValue(info, global_state_v4_key);
182
183 if (isA_CFDictionary(global_v4_state_dict) == NULL) {
184 goto done;
185 }
186
187 service_id = CFDictionaryGetValue(global_v4_state_dict,
188 kSCDynamicStorePropNetPrimaryService);
189
190 if (isA_CFString(service_id) == NULL) {
191 goto done;
192 }
193
194 service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
195 kSCDynamicStoreDomainState,
196 service_id, kSCEntNetIPv4);
197
198 service_dict = CFDictionaryGetValue(info, service);
199
200
201 if (isA_CFDictionary(service_dict) == NULL
202 || CFDictionaryGetCount(service_dict) == 0) {
203 goto done;
204 }
205
206 ident = CFDictionaryGetValue(service_dict, kStoreKeyNetworkSignature);
207 ident = isA_CFString(ident);
208 done:
209 if (ident != NULL) {
210 CFRetain(ident);
211 } else {
212 _SCErrorSet(kSCStatusFailed);
213 }
214 if (info != NULL) {
215 CFRelease(info);
216 }
217 if (global_state_v4_key != NULL) {
218 CFRelease(global_state_v4_key);
219 }
220 if (service != NULL) {
221 CFRelease(service);
222 }
223 if (keys != NULL) {
224 CFRelease(keys);
225 }
226 if (patterns != NULL) {
227 CFRelease(patterns);
228 }
229 if (v4_service_pattern != NULL) {
230 CFRelease(v4_service_pattern);
231 }
232 return (ident);
233 }
234
235 CFArrayRef /* of CFStringRef's */
236 SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc)
237 {
238 CFMutableArrayRef active = NULL;
239 CFIndex count = 0;
240 CFStringRef global_setup_v4_key = NULL;
241 CFDictionaryRef global_v4_dict;
242 int i;
243 CFDictionaryRef info = NULL;
244 CFArrayRef keys = NULL;
245 CFMutableArrayRef patterns = NULL;
246 CFRange range;
247 CFMutableDictionaryRef services_dict = NULL;
248 CFArrayRef service_order;
249 CFStringRef v4_service_pattern = NULL;
250 CFStringRef v6_service_pattern = NULL;
251 const void * * values = NULL;
252 #define KEYS_STATIC_COUNT 10
253 const void * values_static[KEYS_STATIC_COUNT];
254
255 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
256
257 global_setup_v4_key = create_global_setup_v4_key();
258 keys = CFArrayCreate(NULL, (const void * *)&global_setup_v4_key, 1,
259 &kCFTypeArrayCallBacks);
260
261 v4_service_pattern = create_ipv4_services_pattern();
262 CFArrayAppendValue(patterns, v4_service_pattern);
263
264 v6_service_pattern = create_ipv6_services_pattern();
265 CFArrayAppendValue(patterns, v6_service_pattern);
266
267 info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
268
269 if (info == NULL
270 || CFDictionaryGetCount(info) == 0) {
271 goto done;
272 }
273
274 services_dict = CFDictionaryCreateMutableCopy(NULL, 0, info);
275 /*
276 * The service_dict should only contain services and once each
277 * service has been visited, it will be removed from the dictionary.
278 */
279 CFDictionaryRemoveValue(services_dict, global_setup_v4_key);
280
281 global_v4_dict = CFDictionaryGetValue(info, global_setup_v4_key);
282
283 if (isA_CFDictionary(global_v4_dict) != NULL) {
284 service_order = CFDictionaryGetValue(global_v4_dict,
285 kSCPropNetServiceOrder);
286 if (isA_CFArray(service_order) != NULL) {
287 count = CFArrayGetCount(service_order);
288 }
289 }
290
291 active = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
292
293 range = CFRangeMake(0, 0);
294
295 for (i = 0; i < count ; i++) {
296 int j;
297 CFStringRef network_sig;
298 CFStringRef service;
299 CFStringRef service_id;
300 CFDictionaryRef service_info;
301 CFStringRef afs[2] = {kSCEntNetIPv4, kSCEntNetIPv6};
302
303 service_id = CFArrayGetValueAtIndex(service_order, i);
304
305 if (isA_CFString(service_id) == NULL) {
306 continue;
307 }
308
309 for (j = 0; j < 2; j++) {
310 service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
311 kSCDynamicStoreDomainState,
312 service_id, afs[j]);
313
314 service_info = CFDictionaryGetValue(services_dict, service);
315
316 /* Does this service have a signature? */
317 if (isA_CFDictionary(service_info) != NULL) {
318 network_sig = CFDictionaryGetValue(service_info, kStoreKeyNetworkSignature);
319 if (isA_CFString(network_sig) && !CFArrayContainsValue(active, range, network_sig)) {
320 CFArrayAppendValue(active, network_sig);
321 network_sig = NULL;
322 range.length++;
323 }
324 CFDictionaryRemoveValue(services_dict, service);
325 }
326 CFRelease(service);
327 }
328 }
329
330 count = CFDictionaryGetCount(services_dict);
331 if (count != 0) {
332 if (count > KEYS_STATIC_COUNT) {
333 values = (const void * *)malloc(sizeof(*values) * count);
334 } else {
335 values = values_static;
336 }
337 CFDictionaryGetKeysAndValues(services_dict, NULL,
338 (const void * *)values);
339 }
340
341 for (i = 0; i < count; i++) {
342 CFStringRef network_sig;
343 CFDictionaryRef service_dict = (CFDictionaryRef)values[i];
344
345 if (isA_CFDictionary(service_dict) == NULL) {
346 continue;
347 }
348
349 network_sig = CFDictionaryGetValue(service_dict,
350 kStoreKeyNetworkSignature);
351 /* Does this service have a signature? */
352 if (isA_CFString(network_sig) && !CFArrayContainsValue(active, range, network_sig)) {
353 CFArrayAppendValue(active, network_sig);
354 range.length++;
355 network_sig = NULL;
356 }
357 }
358 done:
359 if (info != NULL) {
360 CFRelease(info);
361 }
362 if (services_dict != NULL) {
363 CFRelease(services_dict);
364 }
365 if (global_setup_v4_key != NULL) {
366 CFRelease(global_setup_v4_key);
367 }
368 if (v4_service_pattern != NULL) {
369 CFRelease(v4_service_pattern);
370 }
371 if (v6_service_pattern != NULL) {
372 CFRelease(v6_service_pattern);
373 }
374 if (values != NULL && values != values_static) {
375 free(values);
376 }
377 if (keys != NULL) {
378 CFRelease(keys);
379 }
380 if (patterns != NULL) {
381 CFRelease(patterns);
382 }
383 if (active != NULL && CFArrayGetCount(active) == 0) {
384 CFRelease(active);
385 active = NULL;
386 }
387 if (active == NULL) {
388 _SCErrorSet(kSCStatusFailed);
389 }
390 return (active);
391 }
392
393
394 CFStringRef
395 SCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc,
396 int sock_fd)
397 {
398 CFStringRef addresses_key;
399 int af;
400 CFIndex count;
401 int i;
402 char if_name[IFNAMSIZ];
403 CFStringRef if_name_cf = NULL;
404 conninfo_t * info = NULL;
405 const void * * keys = NULL;
406 #define KEYS_STATIC_COUNT 10
407 const void * keys_static[KEYS_STATIC_COUNT];
408 const void * local_ip_p;
409 CFStringRef local_ip_str = NULL;
410 CFStringRef ret_signature = NULL;
411 CFDictionaryRef service_info = NULL;
412 int status = kSCStatusFailed;
413
414 if (copyconninfo(sock_fd, SAE_CONNID_ANY, &info) != 0) {
415 status = kSCStatusInvalidArgument;
416 goto done;
417 }
418 if ((info->ci_flags & CIF_CONNECTED) == 0
419 || info->ci_src == NULL) {
420 goto done;
421 }
422 af = info->ci_src->sa_family;
423 switch (af) {
424 case AF_INET:
425 addresses_key = kSCPropNetIPv4Addresses;
426 local_ip_p = &((struct sockaddr_in *)
427 (void *)info->ci_src)->sin_addr;
428 break;
429 case AF_INET6:
430 addresses_key = kSCPropNetIPv6Addresses;
431 local_ip_p = &((struct sockaddr_in6 *)
432 (void *)info->ci_src)->sin6_addr;
433 break;
434 default:
435 status = kSCStatusInvalidArgument;
436 goto done;
437 }
438
439 /* search for service with matching IP address and interface name */
440 service_info = copy_services_for_address_family(alloc, af);
441 if (service_info == NULL) {
442 goto done;
443 }
444 local_ip_str = my_IPAddressToCFString(af, local_ip_p);
445 if (local_ip_str == NULL) {
446 goto done;
447 }
448 if (info->ci_ifindex != 0
449 && if_indextoname(info->ci_ifindex, if_name) != NULL) {
450 if_name_cf
451 = CFStringCreateWithCString(NULL, if_name,
452 kCFStringEncodingASCII);
453 }
454 count = CFDictionaryGetCount(service_info);
455 if (count > KEYS_STATIC_COUNT) {
456 keys = (const void * *)malloc(sizeof(*keys) * count);
457 }
458 else {
459 keys = keys_static;
460 }
461 CFDictionaryGetKeysAndValues(service_info, keys, NULL);
462 for (i = 0; i < count; i++) {
463 CFArrayRef addrs;
464 CFRange range;
465 CFStringRef signature;
466 CFDictionaryRef value;
467
468 value = CFDictionaryGetValue(service_info, keys[i]);
469 if (isA_CFDictionary(value) == NULL) {
470 continue;
471 }
472 signature = CFDictionaryGetValue(value,
473 kStoreKeyNetworkSignature);
474 if (isA_CFString(signature) == NULL) {
475 /* no signature */
476 continue;
477 }
478 if (if_name_cf != NULL) {
479 CFStringRef confirmed_if;
480 CFStringRef this_if;
481
482 this_if = CFDictionaryGetValue(value,
483 kSCPropInterfaceName);
484 if (isA_CFString(this_if) == NULL
485 || !CFEqual(this_if, if_name_cf)) {
486 /* no interface or it doesn't match */
487 continue;
488 }
489 confirmed_if
490 = CFDictionaryGetValue(value,
491 kSCPropConfirmedInterfaceName);
492 if (isA_CFString(confirmed_if) != NULL
493 && !CFEqual(confirmed_if, if_name_cf)) {
494 /* confirmed interface doesn't match */
495 continue;
496 }
497 }
498
499 addrs = CFDictionaryGetValue(value, addresses_key);
500 if (isA_CFArray(addrs) == NULL) {
501 continue;
502 }
503 range = CFRangeMake(0, CFArrayGetCount(addrs));
504 if (CFArrayContainsValue(addrs, range, local_ip_str)) {
505 ret_signature = CFRetain(signature);
506 status = kSCStatusOK;
507 break;
508 }
509 }
510
511 done:
512 if (info != NULL) {
513 freeconninfo(info);
514 }
515 if (if_name_cf != NULL) {
516 CFRelease(if_name_cf);
517 }
518 if (local_ip_str != NULL) {
519 CFRelease(local_ip_str);
520 }
521 if (keys != NULL && keys != keys_static) {
522 free(keys);
523 }
524 if (service_info != NULL) {
525 CFRelease(service_info);
526 }
527 if (status != kSCStatusOK) {
528 _SCErrorSet(status);
529 }
530 return (ret_signature);
531 }
532
533 #pragma mark -