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