]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCProxies.c
configd-395.11.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCProxies.c
1 /*
2 * Copyright (c) 2000-2004, 2006-2011 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 * May 18, 2001 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31 #include <TargetConditionals.h>
32 #include <SystemConfiguration/SystemConfiguration.h>
33 #include <SystemConfiguration/SCValidation.h>
34 #include <SystemConfiguration/SCPrivate.h>
35
36 #include <netdb.h>
37
38
39
40
41 CFStringRef
42 SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator)
43 {
44 return SCDynamicStoreKeyCreateNetworkGlobalEntity(allocator,
45 kSCDynamicStoreDomainState,
46 kSCEntNetProxies);
47 }
48
49
50 static void
51 validate_proxy_content(CFMutableDictionaryRef proxies,
52 CFStringRef proxy_enable,
53 CFStringRef proxy_host,
54 CFStringRef proxy_port,
55 const char * proxy_service,
56 int proxy_defaultport)
57 {
58 int enabled = 0;
59 CFNumberRef num;
60
61 num = CFDictionaryGetValue(proxies, proxy_enable);
62 if (num != NULL) {
63 if (!isA_CFNumber(num) ||
64 !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
65 // if we don't like the enabled key/value
66 goto disable;
67 }
68 }
69
70 if (proxy_host != NULL) {
71 CFStringRef host;
72
73 host = CFDictionaryGetValue(proxies, proxy_host);
74 if (((enabled == 0) && (host != NULL)) ||
75 ((enabled != 0) && !isA_CFString(host))) {
76 // pass only valid proxy hosts and only when enabled
77 goto disable;
78 }
79 }
80
81 if (proxy_port != NULL) {
82 CFNumberRef port;
83
84 port = CFDictionaryGetValue(proxies, proxy_port);
85 if (((enabled == 0) && (port != NULL)) ||
86 ((enabled != 0) && (port != NULL) && !isA_CFNumber(port))) {
87 // pass only provided/valid proxy ports and only when enabled
88 goto disable;
89 }
90
91 if ((enabled != 0) && (port == NULL)) {
92 struct servent *service;
93 int s_port;
94
95 service = getservbyname(proxy_service, "tcp");
96 if (service != NULL) {
97 s_port = ntohs(service->s_port);
98 } else {
99 s_port = proxy_defaultport;
100 }
101 num = CFNumberCreate(NULL, kCFNumberIntType, &s_port);
102 CFDictionarySetValue(proxies, proxy_port, num);
103 CFRelease(num);
104 }
105 }
106
107 return;
108
109 disable :
110
111 enabled = 0;
112 num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
113 CFDictionarySetValue(proxies, proxy_enable, num);
114 CFRelease(num);
115 if (proxy_host != NULL) {
116 CFDictionaryRemoveValue(proxies, proxy_host);
117 }
118 if (proxy_port != NULL) {
119 CFDictionaryRemoveValue(proxies, proxy_port);
120 }
121
122 return;
123 }
124
125
126 CFDictionaryRef
127 SCDynamicStoreCopyProxies(SCDynamicStoreRef store)
128 {
129 CFArrayRef array;
130 CFStringRef key;
131 CFMutableDictionaryRef newProxies = NULL;
132 CFNumberRef num;
133 CFDictionaryRef proxies;
134 Boolean tempSession = FALSE;
135
136
137 /* copy proxy information from dynamic store */
138
139 if (store == NULL) {
140 store = SCDynamicStoreCreate(NULL,
141 CFSTR("SCDynamicStoreCopyProxies"),
142 NULL,
143 NULL);
144 if (store == NULL) {
145 return NULL;
146 }
147 tempSession = TRUE;
148 }
149
150 key = SCDynamicStoreKeyCreateProxies(NULL);
151 proxies = SCDynamicStoreCopyValue(store, key);
152 CFRelease(key);
153
154 validate :
155
156 if (proxies != NULL) {
157 if (isA_CFDictionary(proxies)) {
158 newProxies = CFDictionaryCreateMutableCopy(NULL, 0, proxies);
159 }
160 CFRelease(proxies);
161 }
162
163 if (newProxies == NULL) {
164 newProxies = CFDictionaryCreateMutable(NULL,
165 0,
166 &kCFTypeDictionaryKeyCallBacks,
167 &kCFTypeDictionaryValueCallBacks);
168 }
169
170 /* validate [and augment] proxy content */
171
172 validate_proxy_content(newProxies,
173 kSCPropNetProxiesFTPEnable,
174 kSCPropNetProxiesFTPProxy,
175 kSCPropNetProxiesFTPPort,
176 "ftp",
177 21);
178 validate_proxy_content(newProxies,
179 kSCPropNetProxiesGopherEnable,
180 kSCPropNetProxiesGopherProxy,
181 kSCPropNetProxiesGopherPort,
182 "gopher",
183 70);
184 validate_proxy_content(newProxies,
185 kSCPropNetProxiesHTTPEnable,
186 kSCPropNetProxiesHTTPProxy,
187 kSCPropNetProxiesHTTPPort,
188 "http",
189 80);
190 validate_proxy_content(newProxies,
191 kSCPropNetProxiesHTTPSEnable,
192 kSCPropNetProxiesHTTPSProxy,
193 kSCPropNetProxiesHTTPSPort,
194 "https",
195 443);
196 validate_proxy_content(newProxies,
197 kSCPropNetProxiesRTSPEnable,
198 kSCPropNetProxiesRTSPProxy,
199 kSCPropNetProxiesRTSPPort,
200 "rtsp",
201 554);
202 validate_proxy_content(newProxies,
203 kSCPropNetProxiesSOCKSEnable,
204 kSCPropNetProxiesSOCKSProxy,
205 kSCPropNetProxiesSOCKSPort,
206 "socks",
207 1080);
208 if (CFDictionaryContainsKey(newProxies, kSCPropNetProxiesProxyAutoConfigURLString)) {
209 validate_proxy_content(newProxies,
210 kSCPropNetProxiesProxyAutoConfigEnable,
211 kSCPropNetProxiesProxyAutoConfigURLString,
212 NULL,
213 NULL,
214 0);
215
216 // and we can't have both URLString and JavaScript keys
217 CFDictionaryRemoveValue(newProxies, kSCPropNetProxiesProxyAutoConfigJavaScript);
218 } else {
219 validate_proxy_content(newProxies,
220 kSCPropNetProxiesProxyAutoConfigEnable,
221 kSCPropNetProxiesProxyAutoConfigJavaScript,
222 NULL,
223 NULL,
224 0);
225 }
226 validate_proxy_content(newProxies,
227 kSCPropNetProxiesProxyAutoDiscoveryEnable,
228 NULL,
229 NULL,
230 NULL,
231 0);
232
233 // validate FTP passive setting
234 num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesFTPPassive);
235 if (num != NULL) {
236 int enabled = 0;
237
238 if (!isA_CFNumber(num) ||
239 !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
240 // if we don't like the enabled key/value
241 enabled = 1;
242 num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
243 CFDictionarySetValue(newProxies,
244 kSCPropNetProxiesFTPPassive,
245 num);
246 CFRelease(num);
247 }
248 }
249
250 // validate proxy exception list
251 array = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExceptionsList);
252 if (array != NULL) {
253 CFIndex i;
254 CFIndex n;
255
256 n = isA_CFArray(array) ? CFArrayGetCount(array) : 0;
257 for (i = 0; i < n; i++) {
258 CFStringRef str;
259
260 str = CFArrayGetValueAtIndex(array, i);
261 if (!isA_CFString(str)) {
262 // if we don't like the array contents
263 n = 0;
264 break;
265 }
266 }
267
268 if (n == 0) {
269 CFDictionaryRemoveValue(newProxies, kSCPropNetProxiesExceptionsList);
270 }
271 }
272
273 // validate exclude simple hostnames setting
274 num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExcludeSimpleHostnames);
275 if (num != NULL) {
276 int enabled;
277
278 if (!isA_CFNumber(num) ||
279 !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
280 // if we don't like the enabled key/value
281 enabled = 0;
282 num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
283 CFDictionarySetValue(newProxies,
284 kSCPropNetProxiesExcludeSimpleHostnames,
285 num);
286 CFRelease(num);
287 }
288 }
289
290
291 proxies = CFDictionaryCreateCopy(NULL, newProxies);
292 CFRelease(newProxies);
293
294 if (tempSession) CFRelease(store);
295 return proxies;
296 }
297
298
299 CFArrayRef
300 SCNetworkProxiesCopyMatching(CFDictionaryRef globalConfiguration,
301 CFStringRef server,
302 CFStringRef interface)
303 {
304 CFMutableDictionaryRef newProxy;
305 CFArrayRef proxies = NULL;
306 CFDictionaryRef proxy;
307 int sc_status = kSCStatusOK;
308 CFStringRef trimmed = NULL;
309
310 if (!isA_CFDictionary(globalConfiguration)) {
311 // if no proxy configuration
312 _SCErrorSet(kSCStatusOK);
313 return NULL;
314 }
315
316 if (interface != NULL) {
317 CFDictionaryRef scoped;
318
319 if (!isA_CFString(interface) ||
320 (CFStringGetLength(interface) == 0)) {
321 _SCErrorSet(kSCStatusInvalidArgument);
322 return NULL;
323 }
324
325 scoped = CFDictionaryGetValue(globalConfiguration, kSCPropNetProxiesScoped);
326 if (scoped == NULL) {
327 // if no scoped proxy configurations
328 _SCErrorSet(kSCStatusOK);
329 return NULL;
330 }
331
332 if (!isA_CFDictionary(scoped)) {
333 // if corrupt proxy configuration
334 _SCErrorSet(kSCStatusFailed);
335 return NULL;
336 }
337
338 proxy = CFDictionaryGetValue(scoped, interface);
339 if (proxy == NULL) {
340 // if no scoped proxy configuration for this interface
341 _SCErrorSet(kSCStatusOK);
342 return NULL;
343 }
344
345 if (!isA_CFDictionary(proxy)) {
346 // if corrupt proxy configuration
347 _SCErrorSet(kSCStatusFailed);
348 return NULL;
349 }
350
351 // return per-interface proxy configuration
352 proxies = CFArrayCreate(NULL, (const void **)&proxy, 1, &kCFTypeArrayCallBacks);
353 return proxies;
354 }
355
356 if (server != NULL) {
357 CFIndex i;
358 CFMutableArrayRef matching = NULL;
359 CFIndex n;
360 CFIndex server_len;
361 CFArrayRef supplemental;
362
363 trimmed = _SC_trimDomain(server);
364 if (trimmed == NULL) {
365 _SCErrorSet(kSCStatusInvalidArgument);
366 return NULL;
367 }
368
369 server = trimmed;
370 server_len = CFStringGetLength(server);
371
372 supplemental = CFDictionaryGetValue(globalConfiguration, kSCPropNetProxiesSupplemental);
373 if (supplemental == NULL) {
374 // if no supplemental configurations
375 goto done;
376 }
377
378 if (!isA_CFArray(supplemental)) {
379 // if corrupt proxy configuration
380 sc_status = kSCStatusFailed;
381 goto done;
382 }
383
384 n = CFArrayGetCount(supplemental);
385 for (i = 0; i < n; i++) {
386 CFStringRef domain;
387 CFIndex domain_len;
388 CFIndex n_matching;
389
390 proxy = CFArrayGetValueAtIndex(supplemental, i);
391 if (!isA_CFDictionary(proxy)) {
392 // if corrupt proxy configuration
393 continue;
394 }
395
396 domain = CFDictionaryGetValue(proxy, kSCPropNetProxiesSupplementalMatchDomain);
397 if (!isA_CFString(domain)) {
398 // if corrupt proxy configuration
399 continue;
400 }
401
402 domain_len = CFStringGetLength(domain);
403 if (domain_len > 0) {
404 if (!CFStringFindWithOptions(server,
405 domain,
406 CFRangeMake(0, server_len),
407 kCFCompareCaseInsensitive|kCFCompareAnchored|kCFCompareBackwards,
408 NULL)) {
409 // if server does not match this proxy domain (or host)
410 continue;
411 }
412
413 if ((server_len > domain_len) &&
414 !CFStringFindWithOptions(server,
415 CFSTR("."),
416 CFRangeMake(0, server_len - domain_len),
417 kCFCompareCaseInsensitive|kCFCompareAnchored|kCFCompareBackwards,
418 NULL)) {
419 // if server does not match this proxy domain
420 continue;
421 }
422 // } else {
423 // // if this is a "default" (match all) proxy domain
424 }
425
426 if (matching == NULL) {
427 matching = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
428 }
429 n_matching = CFArrayGetCount(matching);
430
431 newProxy = CFDictionaryCreateMutableCopy(NULL, 0, proxy);
432 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplementalMatchDomain);
433 if ((n_matching == 0) ||
434 !CFArrayContainsValue(matching, CFRangeMake(0, n_matching), newProxy)) {
435 // add this matching proxy
436 CFArrayAppendValue(matching, newProxy);
437 }
438 CFRelease(newProxy);
439 }
440
441 if (matching != NULL) {
442 // if we have any supplemental match domains
443 proxies = CFArrayCreateCopy(NULL, matching);
444 CFRelease(matching);
445 goto done;
446 }
447 }
448
449 // no matches, return "global" proxy configuration
450
451 newProxy = CFDictionaryCreateMutableCopy(NULL, 0, globalConfiguration);
452 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesScoped);
453 CFDictionaryRemoveValue(newProxy, kSCPropNetProxiesSupplemental);
454 proxies = CFArrayCreate(NULL, (const void **)&newProxy, 1, &kCFTypeArrayCallBacks);
455 CFRelease(newProxy);
456
457 done :
458
459 if (sc_status != kSCStatusOK) {
460 if (proxies != NULL) {
461 CFRelease(proxies);
462 proxies = NULL;
463 }
464 _SCErrorSet(sc_status);
465 }
466 if (trimmed != NULL) CFRelease(trimmed);
467
468 return proxies;
469 }