Annotation of embedaddon/strongswan/src/libcharon/plugins/osx_attr/osx_attr_handler.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2013 Martin Willi
3: * Copyright (C) 2013 revosec AG
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "osx_attr_handler.h"
17:
18: #include <networking/host.h>
19: #include <utils/debug.h>
20:
21: #include <SystemConfiguration/SCDynamicStore.h>
22:
23: typedef struct private_osx_attr_handler_t private_osx_attr_handler_t;
24:
25: /**
26: * Private data of an osx_attr_handler_t object.
27: */
28: struct private_osx_attr_handler_t {
29:
30: /**
31: * Public interface
32: */
33: osx_attr_handler_t public;
34:
35: /**
36: * Backup of original DNS servers, before we mess with it
37: */
38: CFMutableArrayRef original;
39:
40: /**
41: * Append DNS servers to existing entries, instead of replacing
42: */
43: bool append;
44: };
45:
46: /**
47: * Create a path to the DNS configuration of the Primary IPv4 Service
48: */
49: static CFStringRef create_dns_path(SCDynamicStoreRef store)
50: {
51: CFStringRef service, path = NULL;
52: CFDictionaryRef dict;
53:
54: /* get primary service */
55: dict = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4"));
56: if (dict)
57: {
58: service = CFDictionaryGetValue(dict, CFSTR("PrimaryService"));
59: if (service)
60: {
61: path = CFStringCreateWithFormat(NULL, NULL,
62: CFSTR("State:/Network/Service/%@/DNS"), service);
63: }
64: else
65: {
66: DBG1(DBG_CFG, "SystemConfiguration PrimaryService not known");
67: }
68: CFRelease(dict);
69: }
70: else
71: {
72: DBG1(DBG_CFG, "getting global IPv4 SystemConfiguration failed");
73: }
74: return path;
75: }
76:
77: /**
78: * Create a mutable dictionary from path, a new one if not found
79: */
80: static CFMutableDictionaryRef get_dictionary(SCDynamicStoreRef store,
81: CFStringRef path)
82: {
83: CFDictionaryRef dict;
84: CFMutableDictionaryRef mut = NULL;
85:
86: dict = SCDynamicStoreCopyValue(store, path);
87: if (dict)
88: {
89: if (CFGetTypeID(dict) == CFDictionaryGetTypeID())
90: {
91: mut = CFDictionaryCreateMutableCopy(NULL, 0, dict);
92: }
93: CFRelease(dict);
94: }
95: if (!mut)
96: {
97: mut = CFDictionaryCreateMutable(NULL, 0,
98: &kCFTypeDictionaryKeyCallBacks,
99: &kCFTypeDictionaryValueCallBacks);
100: }
101: return mut;
102: }
103:
104: /**
105: * Create a mutable array from dictionary path, a new one if not found
106: */
107: static CFMutableArrayRef get_array_from_dict(CFDictionaryRef dict,
108: CFStringRef name)
109: {
110: CFArrayRef arr;
111:
112: arr = CFDictionaryGetValue(dict, name);
113: if (arr && CFGetTypeID(arr) == CFArrayGetTypeID())
114: {
115: return CFArrayCreateMutableCopy(NULL, 0, arr);
116: }
117: return CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
118: }
119:
120: /**
121: * Add/Remove a DNS server to the configuration
122: */
123: static bool manage_dns(private_osx_attr_handler_t *this,
124: int family, chunk_t data, bool add)
125: {
126: SCDynamicStoreRef store;
127: CFStringRef path, dns;
128: CFMutableArrayRef arr;
129: CFMutableDictionaryRef dict;
130: CFIndex i;
131: host_t *server;
132: char buf[64];
133: bool success = FALSE;
134:
135: server = host_create_from_chunk(family, data, 0);
136: if (!server)
137: {
138: return FALSE;
139: }
140: snprintf(buf, sizeof(buf), "%H", server);
141: server->destroy(server);
142:
143: store = SCDynamicStoreCreate(NULL, CFSTR("osx-attr"), NULL, NULL);
144: path = create_dns_path(store);
145: if (path)
146: {
147: dict = get_dictionary(store, path);
148: arr = get_array_from_dict(dict, CFSTR("ServerAddresses"));
149: dns = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
150: if (add)
151: {
152: if (!this->append && !this->original)
153: { /* backup original config, start with empty set */
154: this->original = arr;
155: arr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
156: }
157: DBG1(DBG_CFG, "installing %s as DNS server", buf);
158: CFArrayInsertValueAtIndex(arr, 0, dns);
159: }
160: else
161: {
162: i = CFArrayGetFirstIndexOfValue(arr,
163: CFRangeMake(0, CFArrayGetCount(arr)), dns);
164: if (i >= 0)
165: {
166: DBG1(DBG_CFG, "removing %s from DNS servers (%d)", buf, i);
167: CFArrayRemoveValueAtIndex(arr, i);
168: }
169: if (!this->append && this->original && CFArrayGetCount(arr) == 0)
170: { /* restore original config */
171: CFRelease(arr);
172: arr = this->original;
173: this->original = NULL;
174: }
175: }
176: CFRelease(dns);
177: CFDictionarySetValue(dict, CFSTR("ServerAddresses"), arr);
178: CFRelease(arr);
179:
180: success = SCDynamicStoreSetValue(store, path, dict);
181: CFRelease(dict);
182: CFRelease(path);
183: }
184: CFRelease(store);
185:
186: if (!success)
187: {
188: DBG1(DBG_CFG, "adding DNS server to SystemConfiguration failed");
189: }
190: return success;
191: }
192:
193: METHOD(attribute_handler_t, handle, bool,
194: private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
195: configuration_attribute_type_t type, chunk_t data)
196: {
197: switch (type)
198: {
199: case INTERNAL_IP4_DNS:
200: return manage_dns(this, AF_INET, data, TRUE);
201: default:
202: return FALSE;
203: }
204: }
205:
206: METHOD(attribute_handler_t, release, void,
207: private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
208: configuration_attribute_type_t type, chunk_t data)
209: {
210: switch (type)
211: {
212: case INTERNAL_IP4_DNS:
213: manage_dns(this, AF_INET, data, FALSE);
214: break;
215: default:
216: break;
217: }
218: }
219:
220: METHOD(enumerator_t, enumerate_dns, bool,
221: enumerator_t *this, va_list args)
222: {
223: configuration_attribute_type_t *type;
224: chunk_t *data;
225:
226: VA_ARGS_VGET(args, type, data);
227: *type = INTERNAL_IP4_DNS;
228: *data = chunk_empty;
229: this->venumerate = (void*)return_false;
230: return TRUE;
231: }
232:
233: METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
234: private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
235: linked_list_t *vips)
236: {
237: enumerator_t *enumerator;
238:
239: INIT(enumerator,
240: .enumerate = enumerator_enumerate_default,
241: .venumerate = _enumerate_dns,
242: .destroy = (void*)free,
243: );
244: return enumerator;
245: }
246:
247: METHOD(osx_attr_handler_t, destroy, void,
248: private_osx_attr_handler_t *this)
249: {
250: free(this);
251: }
252:
253: /**
254: * See header
255: */
256: osx_attr_handler_t *osx_attr_handler_create()
257: {
258: private_osx_attr_handler_t *this;
259:
260: INIT(this,
261: .public = {
262: .handler = {
263: .handle = _handle,
264: .release = _release,
265: .create_attribute_enumerator = _create_attribute_enumerator,
266: },
267: .destroy = _destroy,
268: },
269: .append = lib->settings->get_bool(lib->settings,
270: "%s.plugins.osx-attr.append", TRUE, lib->ns),
271: );
272:
273: return &this->public;
274: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>