support of setting and getting authority flags
[strongswan.git] / src / charon / sa / tasks / ike_config.c
1 /**
2 * @file ike_config.c
3 *
4 * @brief Implementation of the ike_config task.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Martin Willi
10 * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include "ike_config.h"
25
26 #include <daemon.h>
27 #include <encoding/payloads/cp_payload.h>
28
29 typedef struct private_ike_config_t private_ike_config_t;
30
31 /**
32 * Private members of a ike_config_t task.
33 */
34 struct private_ike_config_t {
35
36 /**
37 * Public methods and task_t interface.
38 */
39 ike_config_t public;
40
41 /**
42 * Assigned IKE_SA.
43 */
44 ike_sa_t *ike_sa;
45
46 /**
47 * Are we the initiator?
48 */
49 bool initiator;
50
51 /**
52 * associated policy with virtual IP configuration
53 */
54 policy_t *policy;
55
56 /**
57 * virtual ip
58 */
59 host_t *virtual_ip;
60
61 /**
62 * list of DNS servers
63 */
64 linked_list_t *dns;
65 };
66
67 /**
68 * build configuration payloads and attributes
69 */
70 static void build_payloads(private_ike_config_t *this, message_t *message,
71 config_type_t type)
72 {
73 cp_payload_t *cp;
74 configuration_attribute_t *ca;
75 chunk_t chunk, prefix;
76
77 if (!this->virtual_ip)
78 {
79 return;
80 }
81
82 cp = cp_payload_create();
83 cp->set_config_type(cp, type);
84
85 ca = configuration_attribute_create();
86
87 if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET)
88 {
89 ca->set_type(ca, INTERNAL_IP4_ADDRESS);
90 if (this->virtual_ip->is_anyaddr(this->virtual_ip))
91 {
92 chunk = chunk_empty;
93 }
94 else
95 {
96 chunk = this->virtual_ip->get_address(this->virtual_ip);
97 }
98 }
99 else
100 {
101 ca->set_type(ca, INTERNAL_IP6_ADDRESS);
102 if (this->virtual_ip->is_anyaddr(this->virtual_ip))
103 {
104 chunk = chunk_empty;
105 }
106 else
107 {
108 prefix = chunk_alloca(1);
109 *prefix.ptr = 64;
110 chunk = this->virtual_ip->get_address(this->virtual_ip);
111 chunk = chunk_cata("cc", chunk, prefix);
112 }
113 }
114 ca->set_value(ca, chunk);
115 cp->add_configuration_attribute(cp, ca);
116
117 /* we currently always add a DNS request if we request an IP */
118 if (this->initiator)
119 {
120 ca = configuration_attribute_create();
121 if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET)
122 {
123 ca->set_type(ca, INTERNAL_IP4_DNS);
124 }
125 else
126 {
127 ca->set_type(ca, INTERNAL_IP6_DNS);
128 }
129 cp->add_configuration_attribute(cp, ca);
130 }
131 else
132 {
133 host_t *ip;
134 iterator_t *iterator = this->dns->create_iterator(this->dns, TRUE);
135 while (iterator->iterate(iterator, (void**)&ip))
136 {
137 ca = configuration_attribute_create();
138 if (ip->get_family(ip) == AF_INET)
139 {
140 ca->set_type(ca, INTERNAL_IP4_DNS);
141 }
142 else
143 {
144 ca->set_type(ca, INTERNAL_IP6_DNS);
145 }
146 chunk = ip->get_address(ip);
147 ca->set_value(ca, chunk);
148 cp->add_configuration_attribute(cp, ca);
149 }
150 iterator->destroy(iterator);
151 }
152 message->add_payload(message, (payload_t*)cp);
153 }
154
155 /**
156 * process a single configuration attribute
157 */
158 static void process_attribute(private_ike_config_t *this,
159 configuration_attribute_t *ca)
160 {
161 host_t *ip;
162 chunk_t addr;
163 int family = AF_INET6;
164
165 switch (ca->get_type(ca))
166 {
167 case INTERNAL_IP4_ADDRESS:
168 family = AF_INET;
169 /* fall */
170 case INTERNAL_IP6_ADDRESS:
171 {
172 addr = ca->get_value(ca);
173 if (addr.len == 0)
174 {
175 ip = host_create_any(family);
176 }
177 else
178 {
179 /* skip prefix byte in IPv6 payload*/
180 if (family == AF_INET6)
181 {
182 addr.len--;
183 }
184 ip = host_create_from_chunk(family, addr, 0);
185 }
186 if (ip && !this->virtual_ip)
187 {
188 this->virtual_ip = ip;
189 }
190 break;
191 }
192 case INTERNAL_IP4_DNS:
193 family = AF_INET;
194 /* fall */
195 case INTERNAL_IP6_DNS:
196 {
197 addr = ca->get_value(ca);
198 if (addr.len == 0)
199 {
200 ip = host_create_any(family);
201 }
202 else
203 {
204 ip = host_create_from_chunk(family, addr, 0);
205 }
206 if (ip)
207 {
208 this->dns->insert_last(this->dns, ip);
209 }
210 break;
211 }
212 case INTERNAL_IP4_NBNS:
213 case INTERNAL_IP6_NBNS:
214 /* TODO */
215 default:
216 DBG1(DBG_IKE, "ignoring %N config attribute",
217 configuration_attribute_type_names,
218 ca->get_type(ca));
219 break;
220 }
221 }
222
223 /**
224 * Scan for configuration payloads and attributes
225 */
226 static void process_payloads(private_ike_config_t *this, message_t *message)
227 {
228 iterator_t *iterator, *attributes;
229 payload_t *payload;
230
231 iterator = message->get_payload_iterator(message);
232 while (iterator->iterate(iterator, (void**)&payload))
233 {
234 if (payload->get_type(payload) == CONFIGURATION)
235 {
236 cp_payload_t *cp = (cp_payload_t*)payload;
237 configuration_attribute_t *ca;
238 switch (cp->get_config_type(cp))
239 {
240 case CFG_REQUEST:
241 case CFG_REPLY:
242 {
243 attributes = cp->create_attribute_iterator(cp);
244 while (attributes->iterate(attributes, (void**)&ca))
245 {
246 process_attribute(this, ca);
247 }
248 attributes->destroy(attributes);
249 break;
250 }
251 default:
252 DBG1(DBG_IKE, "ignoring %N config payload",
253 config_type_names, cp->get_config_type(cp));
254 break;
255 }
256 }
257 }
258 iterator->destroy(iterator);
259 }
260
261 /**
262 * Implementation of task_t.process for initiator
263 */
264 static status_t build_i(private_ike_config_t *this, message_t *message)
265 {
266 if (message->get_exchange_type(message) != IKE_SA_INIT)
267 {
268 this->virtual_ip = this->policy->get_virtual_ip(this->policy, NULL);
269
270 build_payloads(this, message, CFG_REQUEST);
271 }
272
273 return NEED_MORE;
274 }
275
276 /**
277 * Implementation of task_t.process for responder
278 */
279 static status_t process_r(private_ike_config_t *this, message_t *message)
280 {
281 if (message->get_exchange_type(message) != IKE_SA_INIT)
282 {
283 process_payloads(this, message);
284 }
285 return NEED_MORE;
286 }
287
288 /**
289 * Implementation of task_t.build for responder
290 */
291 static status_t build_r(private_ike_config_t *this, message_t *message)
292 {
293 if (message->get_exchange_type(message) != IKE_SA_INIT)
294 {
295 this->policy = this->ike_sa->get_policy(this->ike_sa);
296
297 if (this->policy && this->virtual_ip)
298 {
299 host_t *ip;
300
301 DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
302 ip = this->policy->get_virtual_ip(this->policy, this->virtual_ip);
303 if (ip == NULL || ip->is_anyaddr(ip))
304 {
305 DBG1(DBG_IKE, "not assigning a virtual IP to peer");
306 return SUCCESS;
307 }
308 DBG1(DBG_IKE, "assigning virtual IP %H to peer", ip);
309 this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, ip);
310
311 this->virtual_ip->destroy(this->virtual_ip);
312 this->virtual_ip = ip;
313
314 /* DNS is for testing only */
315 if (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS)
316 {
317 ip->destroy(ip);
318 ip = host_create_from_string("10.3.0.1", 0);
319 this->dns->insert_last(this->dns, ip);
320 ip = host_create_from_string("10.3.0.2", 0);
321 this->dns->insert_last(this->dns, ip);
322 }
323
324 build_payloads(this, message, CFG_REPLY);
325 }
326 return SUCCESS;
327 }
328 return NEED_MORE;
329 }
330
331 /**
332 * Implementation of task_t.process for initiator
333 */
334 static status_t process_i(private_ike_config_t *this, message_t *message)
335 {
336 if (message->get_exchange_type(message) != IKE_SA_INIT)
337 {
338 host_t *ip;
339
340 DESTROY_IF(this->virtual_ip);
341 this->virtual_ip = NULL;
342
343 process_payloads(this, message);
344
345 if (this->virtual_ip)
346 {
347 this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
348
349 while (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS)
350 {
351 this->ike_sa->add_dns_server(this->ike_sa, ip);
352 ip->destroy(ip);
353 }
354 }
355 return SUCCESS;
356 }
357 return NEED_MORE;
358 }
359
360 /**
361 * Implementation of task_t.get_type
362 */
363 static task_type_t get_type(private_ike_config_t *this)
364 {
365 return IKE_CONFIG;
366 }
367
368 /**
369 * Implementation of task_t.migrate
370 */
371 static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
372 {
373 DESTROY_IF(this->virtual_ip);
374 this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
375
376 this->ike_sa = ike_sa;
377 this->virtual_ip = NULL;
378 this->dns = linked_list_create();
379 }
380
381 /**
382 * Implementation of task_t.destroy
383 */
384 static void destroy(private_ike_config_t *this)
385 {
386 DESTROY_IF(this->virtual_ip);
387 this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
388 free(this);
389 }
390
391 /*
392 * Described in header.
393 */
394 ike_config_t *ike_config_create(ike_sa_t *ike_sa, policy_t *policy)
395 {
396 private_ike_config_t *this = malloc_thing(private_ike_config_t);
397
398 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
399 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
400 this->public.task.destroy = (void(*)(task_t*))destroy;
401
402 if (policy)
403 {
404 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
405 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
406 this->initiator = TRUE;
407 }
408 else
409 {
410 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
411 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
412 this->initiator = FALSE;
413 }
414
415 this->ike_sa = ike_sa;
416 this->policy = policy;
417 this->virtual_ip = NULL;
418 this->dns = linked_list_create();
419
420 return &this->public;
421 }