40b8c839adfde90bd956b772ed49694085270cc0
[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 * $Id$
17 */
18
19 #include "ike_config.h"
20
21 #include <daemon.h>
22 #include <encoding/payloads/cp_payload.h>
23
24 #define DNS_SERVER_MAX 2
25 #define NBNS_SERVER_MAX 2
26
27 typedef struct private_ike_config_t private_ike_config_t;
28
29 /**
30 * Private members of a ike_config_t task.
31 */
32 struct private_ike_config_t {
33
34 /**
35 * Public methods and task_t interface.
36 */
37 ike_config_t public;
38
39 /**
40 * Assigned IKE_SA.
41 */
42 ike_sa_t *ike_sa;
43
44 /**
45 * Are we the initiator?
46 */
47 bool initiator;
48
49 /**
50 * virtual ip
51 */
52 host_t *virtual_ip;
53
54 /**
55 * list of DNS servers
56 */
57 linked_list_t *dns;
58 };
59
60 /**
61 * build configuration payloads and attributes
62 */
63 static void build_payloads(private_ike_config_t *this, message_t *message,
64 config_type_t type)
65 {
66 cp_payload_t *cp;
67 configuration_attribute_t *ca;
68 chunk_t chunk, prefix;
69
70 if (!this->virtual_ip)
71 {
72 return;
73 }
74
75 cp = cp_payload_create();
76 cp->set_config_type(cp, type);
77
78 ca = configuration_attribute_create();
79
80 if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET)
81 {
82 ca->set_type(ca, INTERNAL_IP4_ADDRESS);
83 if (this->virtual_ip->is_anyaddr(this->virtual_ip))
84 {
85 chunk = chunk_empty;
86 }
87 else
88 {
89 chunk = this->virtual_ip->get_address(this->virtual_ip);
90 }
91 }
92 else
93 {
94 ca->set_type(ca, INTERNAL_IP6_ADDRESS);
95 if (this->virtual_ip->is_anyaddr(this->virtual_ip))
96 {
97 chunk = chunk_empty;
98 }
99 else
100 {
101 prefix = chunk_alloca(1);
102 *prefix.ptr = 64;
103 chunk = this->virtual_ip->get_address(this->virtual_ip);
104 chunk = chunk_cata("cc", chunk, prefix);
105 }
106 }
107 ca->set_value(ca, chunk);
108 cp->add_configuration_attribute(cp, ca);
109
110 /* we currently always add a DNS request if we request an IP */
111 if (this->initiator)
112 {
113 ca = configuration_attribute_create();
114 if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET)
115 {
116 ca->set_type(ca, INTERNAL_IP4_DNS);
117 }
118 else
119 {
120 ca->set_type(ca, INTERNAL_IP6_DNS);
121 }
122 cp->add_configuration_attribute(cp, ca);
123 }
124 else
125 {
126 host_t *ip;
127 iterator_t *iterator = this->dns->create_iterator(this->dns, TRUE);
128 while (iterator->iterate(iterator, (void**)&ip))
129 {
130 ca = configuration_attribute_create();
131 if (ip->get_family(ip) == AF_INET)
132 {
133 ca->set_type(ca, INTERNAL_IP4_DNS);
134 }
135 else
136 {
137 ca->set_type(ca, INTERNAL_IP6_DNS);
138 }
139 chunk = ip->get_address(ip);
140 ca->set_value(ca, chunk);
141 cp->add_configuration_attribute(cp, ca);
142 }
143 iterator->destroy(iterator);
144 }
145 message->add_payload(message, (payload_t*)cp);
146 }
147
148 /**
149 * process a single configuration attribute
150 */
151 static void process_attribute(private_ike_config_t *this,
152 configuration_attribute_t *ca)
153 {
154 host_t *ip;
155 chunk_t addr;
156 int family = AF_INET6;
157
158 switch (ca->get_type(ca))
159 {
160 case INTERNAL_IP4_ADDRESS:
161 family = AF_INET;
162 /* fall */
163 case INTERNAL_IP6_ADDRESS:
164 {
165 addr = ca->get_value(ca);
166 if (addr.len == 0)
167 {
168 ip = host_create_any(family);
169 }
170 else
171 {
172 /* skip prefix byte in IPv6 payload*/
173 if (family == AF_INET6)
174 {
175 addr.len--;
176 }
177 ip = host_create_from_chunk(family, addr, 0);
178 }
179 if (ip && !this->virtual_ip)
180 {
181 this->virtual_ip = ip;
182 }
183 break;
184 }
185 case INTERNAL_IP4_DNS:
186 family = AF_INET;
187 /* fall */
188 case INTERNAL_IP6_DNS:
189 {
190 addr = ca->get_value(ca);
191 if (addr.len == 0)
192 {
193 ip = host_create_any(family);
194 }
195 else
196 {
197 ip = host_create_from_chunk(family, addr, 0);
198 }
199 if (ip)
200 {
201 this->dns->insert_last(this->dns, ip);
202 }
203 break;
204 }
205 case INTERNAL_IP4_NBNS:
206 case INTERNAL_IP6_NBNS:
207 /* TODO */
208 default:
209 DBG1(DBG_IKE, "ignoring %N config attribute",
210 configuration_attribute_type_names,
211 ca->get_type(ca));
212 break;
213 }
214 }
215
216 /**
217 * Scan for configuration payloads and attributes
218 */
219 static void process_payloads(private_ike_config_t *this, message_t *message)
220 {
221 iterator_t *iterator, *attributes;
222 payload_t *payload;
223
224 iterator = message->get_payload_iterator(message);
225 while (iterator->iterate(iterator, (void**)&payload))
226 {
227 if (payload->get_type(payload) == CONFIGURATION)
228 {
229 cp_payload_t *cp = (cp_payload_t*)payload;
230 configuration_attribute_t *ca;
231 switch (cp->get_config_type(cp))
232 {
233 case CFG_REQUEST:
234 case CFG_REPLY:
235 {
236 attributes = cp->create_attribute_iterator(cp);
237 while (attributes->iterate(attributes, (void**)&ca))
238 {
239 process_attribute(this, ca);
240 }
241 attributes->destroy(attributes);
242 break;
243 }
244 default:
245 DBG1(DBG_IKE, "ignoring %N config payload",
246 config_type_names, cp->get_config_type(cp));
247 break;
248 }
249 }
250 }
251 iterator->destroy(iterator);
252 }
253
254 /**
255 * Implementation of task_t.process for initiator
256 */
257 static status_t build_i(private_ike_config_t *this, message_t *message)
258 {
259 if (message->get_exchange_type(message) == IKE_AUTH &&
260 message->get_payload(message, ID_INITIATOR))
261 {
262 peer_cfg_t *config;
263 host_t *vip;
264
265 /* reuse virtual IP if we already have one */
266 vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
267 if (!vip)
268 {
269 config = this->ike_sa->get_peer_cfg(this->ike_sa);
270 vip = config->get_virtual_ip(config);
271 }
272 if (vip)
273 {
274 this->virtual_ip = vip->clone(vip);
275 }
276
277 build_payloads(this, message, CFG_REQUEST);
278 }
279
280 return NEED_MORE;
281 }
282
283 /**
284 * Implementation of task_t.process for responder
285 */
286 static status_t process_r(private_ike_config_t *this, message_t *message)
287 {
288 if (message->get_exchange_type(message) == IKE_AUTH &&
289 message->get_payload(message, ID_INITIATOR))
290 {
291 process_payloads(this, message);
292 }
293 return NEED_MORE;
294 }
295
296 /**
297 * Implementation of task_t.build for responder
298 */
299 static status_t build_r(private_ike_config_t *this, message_t *message)
300 {
301 if (message->get_exchange_type(message) == IKE_AUTH &&
302 message->get_payload(message, EXTENSIBLE_AUTHENTICATION) == NULL)
303 {
304 peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
305
306 if (config && this->virtual_ip)
307 {
308 host_t *ip = NULL;
309
310 DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
311 if (config->get_pool(config))
312 {
313 ip = charon->attributes->acquire_address(charon->attributes,
314 config->get_pool(config),
315 this->ike_sa->get_other_id(this->ike_sa),
316 this->ike_sa->get_other_auth(this->ike_sa),
317 this->virtual_ip);
318 }
319 if (ip == NULL)
320 {
321 DBG1(DBG_IKE, "no virtual IP found, sending %N",
322 notify_type_names, INTERNAL_ADDRESS_FAILURE);
323 message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
324 chunk_empty);
325 return SUCCESS;
326 }
327 DBG1(DBG_IKE, "assigning virtual IP %H to peer", ip);
328 this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, ip);
329
330 this->virtual_ip->destroy(this->virtual_ip);
331 this->virtual_ip = ip;
332
333 build_payloads(this, message, CFG_REPLY);
334 }
335 return SUCCESS;
336 }
337 return NEED_MORE;
338 }
339
340 /**
341 * Implementation of task_t.process for initiator
342 */
343 static status_t process_i(private_ike_config_t *this, message_t *message)
344 {
345 if (message->get_exchange_type(message) == IKE_AUTH &&
346 !message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
347 {
348 host_t *ip;
349 peer_cfg_t *config;
350
351 DESTROY_IF(this->virtual_ip);
352 this->virtual_ip = NULL;
353
354 process_payloads(this, message);
355
356 if (this->virtual_ip == NULL)
357 { /* force a configured virtual IP, even if server didn't return one */
358 config = this->ike_sa->get_peer_cfg(this->ike_sa);
359 this->virtual_ip = config->get_virtual_ip(config);
360 if (this->virtual_ip)
361 {
362 this->virtual_ip = this->virtual_ip->clone(this->virtual_ip);
363 }
364 }
365
366 if (this->virtual_ip && !this->virtual_ip->is_anyaddr(this->virtual_ip))
367 {
368 this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
369
370 while (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS)
371 {
372 if (!ip->is_anyaddr(ip))
373 {
374 this->ike_sa->add_dns_server(this->ike_sa, ip);
375 }
376 ip->destroy(ip);
377 }
378 }
379 return SUCCESS;
380 }
381 return NEED_MORE;
382 }
383
384 /**
385 * Implementation of task_t.get_type
386 */
387 static task_type_t get_type(private_ike_config_t *this)
388 {
389 return IKE_CONFIG;
390 }
391
392 /**
393 * Implementation of task_t.migrate
394 */
395 static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
396 {
397 DESTROY_IF(this->virtual_ip);
398 this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
399
400 this->ike_sa = ike_sa;
401 this->virtual_ip = NULL;
402 this->dns = linked_list_create();
403 }
404
405 /**
406 * Implementation of task_t.destroy
407 */
408 static void destroy(private_ike_config_t *this)
409 {
410 DESTROY_IF(this->virtual_ip);
411 this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
412 free(this);
413 }
414
415 /*
416 * Described in header.
417 */
418 ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
419 {
420 private_ike_config_t *this = malloc_thing(private_ike_config_t);
421
422 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
423 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
424 this->public.task.destroy = (void(*)(task_t*))destroy;
425
426 this->initiator = initiator;
427 this->ike_sa = ike_sa;
428 this->virtual_ip = NULL;
429 this->dns = linked_list_create();
430
431 if (initiator)
432 {
433 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
434 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
435 }
436 else
437 {
438 int i;
439
440 for (i = 1; i <= DNS_SERVER_MAX; i++)
441 {
442 char dns_key[12], *dns_str;
443
444 snprintf(dns_key, sizeof(dns_key), "charon.dns%d", i);
445 dns_str = lib->settings->get_str(lib->settings, dns_key, NULL);
446 if (dns_str)
447 {
448 host_t *dns = host_create_from_string(dns_str, 0);
449
450 if (dns)
451 {
452 DBG2(DBG_CFG, "assigning DNS server %H to peer", dns);
453 this->dns->insert_last(this->dns, dns);
454 }
455 }
456 }
457 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
458 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
459 }
460
461 return &this->public;
462 }