]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/osx_attr/osx_attr_handler.c
Fixed some typos, courtesy of codespell
[thirdparty/strongswan.git] / src / libcharon / plugins / osx_attr / osx_attr_handler.c
CommitLineData
45dcf4df
MW
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
23typedef struct private_osx_attr_handler_t private_osx_attr_handler_t;
24
25/**
26 * Private data of an osx_attr_handler_t object.
27 */
28struct private_osx_attr_handler_t {
29
30 /**
31 * Public interface
32 */
33 osx_attr_handler_t public;
61d6cdb9
MW
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;
45dcf4df
MW
44};
45
46/**
47 * Create a path to the DNS configuration of the Primary IPv4 Service
48 */
49static 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 */
80static 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 */
107static 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 */
61d6cdb9
MW
123static bool manage_dns(private_osx_attr_handler_t *this,
124 int family, chunk_t data, bool add)
45dcf4df
MW
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 {
61d6cdb9 152 if (!this->append && !this->original)
2db6d5b8 153 { /* backup original config, start with empty set */
61d6cdb9
MW
154 this->original = arr;
155 arr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
156 }
45dcf4df
MW
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 }
61d6cdb9
MW
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 }
45dcf4df
MW
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
193METHOD(attribute_handler_t, handle, bool,
b9be25ea 194 private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
45dcf4df
MW
195 configuration_attribute_type_t type, chunk_t data)
196{
197 switch (type)
198 {
199 case INTERNAL_IP4_DNS:
61d6cdb9 200 return manage_dns(this, AF_INET, data, TRUE);
45dcf4df
MW
201 default:
202 return FALSE;
203 }
204}
205
206METHOD(attribute_handler_t, release, void,
b9be25ea 207 private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
45dcf4df
MW
208 configuration_attribute_type_t type, chunk_t data)
209{
210 switch (type)
211 {
212 case INTERNAL_IP4_DNS:
61d6cdb9 213 manage_dns(this, AF_INET, data, FALSE);
45dcf4df
MW
214 break;
215 default:
216 break;
217 }
218}
219
220METHOD(enumerator_t, enumerate_dns, bool,
95a63bf2 221 enumerator_t *this, va_list args)
45dcf4df 222{
95a63bf2
TB
223 configuration_attribute_type_t *type;
224 chunk_t *data;
225
226 VA_ARGS_VGET(args, type, data);
45dcf4df
MW
227 *type = INTERNAL_IP4_DNS;
228 *data = chunk_empty;
95a63bf2 229 this->venumerate = (void*)return_false;
45dcf4df
MW
230 return TRUE;
231}
232
233METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
b9be25ea 234 private_osx_attr_handler_t *this, ike_sa_t *ike_sa,
45dcf4df
MW
235 linked_list_t *vips)
236{
237 enumerator_t *enumerator;
238
239 INIT(enumerator,
95a63bf2
TB
240 .enumerate = enumerator_enumerate_default,
241 .venumerate = _enumerate_dns,
45dcf4df
MW
242 .destroy = (void*)free,
243 );
244 return enumerator;
245}
246
247METHOD(osx_attr_handler_t, destroy, void,
248 private_osx_attr_handler_t *this)
249{
250 free(this);
251}
252
253/**
254 * See header
255 */
256osx_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 },
61d6cdb9
MW
269 .append = lib->settings->get_bool(lib->settings,
270 "%s.plugins.osx-attr.append", TRUE, lib->ns),
45dcf4df
MW
271 );
272
273 return &this->public;
274}