added firewalling support when using virtual IPs
[strongswan.git] / src / charon / sa / tasks / child_create.c
1 /**
2 * @file child_create.c
3 *
4 * @brief Implementation of the child_create task.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
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 "child_create.h"
25
26 #include <daemon.h>
27 #include <crypto/diffie_hellman.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/ts_payload.h>
30 #include <encoding/payloads/nonce_payload.h>
31 #include <encoding/payloads/notify_payload.h>
32
33
34 typedef struct private_child_create_t private_child_create_t;
35
36 /**
37 * Private members of a child_create_t task.
38 */
39 struct private_child_create_t {
40
41 /**
42 * Public methods and task_t interface.
43 */
44 child_create_t public;
45
46 /**
47 * Assigned IKE_SA.
48 */
49 ike_sa_t *ike_sa;
50
51 /**
52 * Are we the initiator?
53 */
54 bool initiator;
55
56 /**
57 * nonce chosen by us
58 */
59 chunk_t my_nonce;
60
61 /**
62 * nonce chosen by peer
63 */
64 chunk_t other_nonce;
65
66 /**
67 * policy to create the CHILD_SA from
68 */
69 policy_t *policy;
70
71 /**
72 * list of proposal candidates
73 */
74 linked_list_t *proposals;
75
76 /**
77 * selected proposal to use for CHILD_SA
78 */
79 proposal_t *proposal;
80
81 /**
82 * traffic selectors for initiators side
83 */
84 linked_list_t *tsi;
85
86 /**
87 * traffic selectors for responders side
88 */
89 linked_list_t *tsr;
90
91 /**
92 * mode the new CHILD_SA uses (transport/tunnel/beet)
93 */
94 mode_t mode;
95
96 /**
97 * reqid to use if we are rekeying
98 */
99 u_int32_t reqid;
100
101 /**
102 * CHILD_SA which gets established
103 */
104 child_sa_t *child_sa;
105 };
106
107 /**
108 * get the nonce from a message
109 */
110 static status_t get_nonce(message_t *message, chunk_t *nonce)
111 {
112 nonce_payload_t *payload;
113
114 payload = (nonce_payload_t*)message->get_payload(message, NONCE);
115 if (payload == NULL)
116 {
117 return FAILED;
118 }
119 *nonce = payload->get_nonce(payload);
120 return NEED_MORE;
121 }
122
123 /**
124 * generate a new nonce to include in a CREATE_CHILD_SA message
125 */
126 static status_t generate_nonce(chunk_t *nonce)
127 {
128 status_t status;
129 randomizer_t *randomizer = randomizer_create();
130
131 status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE,
132 nonce);
133 randomizer->destroy(randomizer);
134 if (status != SUCCESS)
135 {
136 DBG1(DBG_IKE, "error generating random nonce value");
137 return FAILED;
138 }
139 return SUCCESS;
140 }
141
142 /**
143 * Check a list of traffic selectors if any selector belongs to host
144 */
145 static bool ts_list_is_host(linked_list_t *list, host_t *host)
146 {
147 traffic_selector_t *ts;
148 bool is_host = TRUE;
149 iterator_t *iterator = list->create_iterator(list, TRUE);
150
151 while (is_host && iterator->iterate(iterator, (void**)&ts))
152 {
153 is_host = is_host && ts->is_host(ts, host);
154 }
155 iterator->destroy(iterator);
156 return is_host;
157 }
158
159 /**
160 * Install a CHILD_SA for usage
161 */
162 static status_t select_and_install(private_child_create_t *this)
163 {
164 prf_plus_t *prf_plus;
165 status_t status;
166 chunk_t nonce_i, nonce_r, seed;
167 linked_list_t *my_ts, *other_ts;
168 host_t *me, *other, *other_vip, *my_vip;
169
170 if (this->proposals == NULL || this->tsi == NULL || this->tsr == NULL)
171 {
172 SIG(CHILD_UP_FAILED, "SA/TS payloads missing in message");
173 return FAILED;
174 }
175
176 if (this->initiator)
177 {
178 nonce_i = this->my_nonce;
179 nonce_r = this->other_nonce;
180 my_ts = this->tsi;
181 other_ts = this->tsr;
182 }
183 else
184 {
185 nonce_r = this->my_nonce;
186 nonce_i = this->other_nonce;
187 my_ts = this->tsr;
188 other_ts = this->tsi;
189 }
190
191 me = this->ike_sa->get_my_host(this->ike_sa);
192 other = this->ike_sa->get_other_host(this->ike_sa);
193 my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
194 other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
195
196 this->proposal = this->policy->select_proposal(this->policy, this->proposals);
197
198 if (this->initiator && my_vip)
199 { /* if we have a virtual IP, shorten our TS to the minimum */
200 my_ts = this->policy->select_my_traffic_selectors(this->policy, my_ts,
201 my_vip);
202 /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
203 this->child_sa->set_virtual_ip(this->child_sa, my_vip);
204 }
205 else
206 { /* shorten in the host2host case only */
207 my_ts = this->policy->select_my_traffic_selectors(this->policy,
208 my_ts, me);
209 }
210 if (other_vip)
211 { /* if other has a virtual IP, shorten it's traffic selectors to it */
212 other_ts = this->policy->select_other_traffic_selectors(this->policy,
213 other_ts, other_vip);
214 }
215 else
216 { /* use his host for the host2host case */
217 other_ts = this->policy->select_other_traffic_selectors(this->policy,
218 other_ts, other);
219 }
220 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
221 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
222 if (this->initiator)
223 {
224 this->tsi = my_ts;
225 this->tsr = other_ts;
226 }
227 else
228 {
229 this->tsr = my_ts;
230 this->tsi = other_ts;
231 }
232
233 if (this->proposal == NULL ||
234 this->tsi->get_count(this->tsi) == 0 ||
235 this->tsr->get_count(this->tsr) == 0)
236 {
237 SIG(CHILD_UP_FAILED, "no acceptable proposal found");
238 return FAILED;
239 }
240
241 if (!this->initiator)
242 {
243 /* check if requested mode is acceptable, downgrade if required */
244 switch (this->mode)
245 {
246 case MODE_TRANSPORT:
247 if (!ts_list_is_host(this->tsi, other) ||
248 !ts_list_is_host(this->tsr, me))
249 {
250 this->mode = MODE_TUNNEL;
251 DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
252 }
253 else if (this->ike_sa->is_natt_enabled(this->ike_sa))
254 {
255 this->mode = MODE_TUNNEL;
256 DBG1(DBG_IKE, "not using tranport mode, connection NATed");
257 }
258 break;
259 case MODE_BEET:
260 if (!ts_list_is_host(this->tsi, NULL) ||
261 !ts_list_is_host(this->tsr, NULL))
262 {
263 this->mode = MODE_TUNNEL;
264 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
265 }
266 break;
267 default:
268 break;
269 }
270 }
271
272 seed = chunk_cata("cc", nonce_i, nonce_r);
273 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
274
275 if (this->initiator)
276 {
277 status = this->child_sa->update(this->child_sa, this->proposal,
278 this->mode, prf_plus);
279 }
280 else
281 {
282 status = this->child_sa->add(this->child_sa, this->proposal,
283 this->mode, prf_plus);
284 }
285 prf_plus->destroy(prf_plus);
286
287 if (status != SUCCESS)
288 {
289 SIG(CHILD_UP_FAILED, "unable to install IPsec SA (SAD) in kernel");
290 return status;
291 }
292
293 status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
294 this->mode);
295
296 if (status != SUCCESS)
297 {
298 SIG(CHILD_UP_FAILED, "unable to install IPsec policies (SPD) in kernel");
299 return status;
300 }
301 /* add to IKE_SA, and remove from task */
302 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
303 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
304 this->child_sa = NULL;
305 return SUCCESS;
306 }
307
308 /**
309 * build the payloads for the message
310 */
311 static void build_payloads(private_child_create_t *this, message_t *message)
312 {
313 sa_payload_t *sa_payload;
314 ts_payload_t *ts_payload;
315 nonce_payload_t *nonce_payload;
316
317 /* add SA payload */
318 if (this->initiator)
319 {
320 sa_payload = sa_payload_create_from_proposal_list(this->proposals);
321 }
322 else
323 {
324 sa_payload = sa_payload_create_from_proposal(this->proposal);
325 }
326 message->add_payload(message, (payload_t*)sa_payload);
327
328 /* add TSi/TSr payloads */
329 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
330 message->add_payload(message, (payload_t*)ts_payload);
331 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
332 message->add_payload(message, (payload_t*)ts_payload);
333
334 /* add nonce payload if not in IKE_AUTH */
335 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
336 {
337 nonce_payload = nonce_payload_create();
338 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
339 message->add_payload(message, (payload_t*)nonce_payload);
340 }
341
342 /* add a notify if we are not in tunnel mode */
343 switch (this->mode)
344 {
345 case MODE_TRANSPORT:
346 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
347 break;
348 case MODE_BEET:
349 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
350 break;
351 default:
352 break;
353 }
354 }
355
356 /**
357 * Read payloads from message
358 */
359 static void process_payloads(private_child_create_t *this, message_t *message)
360 {
361 iterator_t *iterator;
362 payload_t *payload;
363 sa_payload_t *sa_payload;
364 ts_payload_t *ts_payload;
365 notify_payload_t *notify_payload;
366
367 /* defaults to TUNNEL mode */
368 this->mode = MODE_TUNNEL;
369
370 iterator = message->get_payload_iterator(message);
371 while (iterator->iterate(iterator, (void**)&payload))
372 {
373 switch (payload->get_type(payload))
374 {
375 case SECURITY_ASSOCIATION:
376 sa_payload = (sa_payload_t*)payload;
377 this->proposals = sa_payload->get_proposals(sa_payload);
378 break;
379 case TRAFFIC_SELECTOR_INITIATOR:
380 ts_payload = (ts_payload_t*)payload;
381 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
382 break;
383 case TRAFFIC_SELECTOR_RESPONDER:
384 ts_payload = (ts_payload_t*)payload;
385 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
386 break;
387 case NOTIFY:
388 notify_payload = (notify_payload_t*)payload;
389 switch (notify_payload ->get_notify_type(notify_payload ))
390 {
391 case USE_TRANSPORT_MODE:
392 this->mode = MODE_TRANSPORT;
393 break;
394 case USE_BEET_MODE:
395 this->mode = MODE_BEET;
396 break;
397 default:
398 break;
399 }
400 break;
401 default:
402 break;
403 }
404 }
405 iterator->destroy(iterator);
406 }
407
408 /**
409 * Implementation of task_t.build for initiator
410 */
411 static status_t build_i(private_child_create_t *this, message_t *message)
412 {
413 host_t *me, *other, *vip;
414
415 switch (message->get_exchange_type(message))
416 {
417 case IKE_SA_INIT:
418 return get_nonce(message, &this->my_nonce);
419 case CREATE_CHILD_SA:
420 if (generate_nonce(&this->my_nonce) != SUCCESS)
421 {
422 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
423 return SUCCESS;
424 }
425 break;
426 default:
427 break;
428 }
429
430 SIG(CHILD_UP_START, "establishing CHILD_SA");
431
432 me = this->ike_sa->get_my_host(this->ike_sa);
433 other = this->ike_sa->get_other_host(this->ike_sa);
434 vip = this->policy->get_virtual_ip(this->policy, NULL);
435
436 if (vip)
437 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
438 this->tsi = this->policy->get_my_traffic_selectors(this->policy, NULL);
439 vip->destroy(vip);
440 }
441 else
442 { /* but shorten a 0.0.0.0/0 subnet to the actual address if host2host */
443 this->tsi = this->policy->get_my_traffic_selectors(this->policy, me);
444 }
445 this->tsr = this->policy->get_other_traffic_selectors(this->policy, other);
446 this->proposals = this->policy->get_proposals(this->policy);
447 this->mode = this->policy->get_mode(this->policy);
448
449 this->child_sa = child_sa_create(me, other,
450 this->ike_sa->get_my_id(this->ike_sa),
451 this->ike_sa->get_other_id(this->ike_sa),
452 this->policy, this->reqid,
453 this->ike_sa->is_natt_enabled(this->ike_sa));
454
455 if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
456 {
457 SIG(CHILD_UP_FAILED, "unable to allocate SPIs from kernel");
458 return FAILED;
459 }
460
461 build_payloads(this, message);
462
463 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
464 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
465 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
466 this->tsi = NULL;
467 this->tsr = NULL;
468 this->proposals = NULL;
469
470 return NEED_MORE;
471 }
472
473 /**
474 * Implementation of task_t.process for initiator
475 */
476 static status_t process_r(private_child_create_t *this, message_t *message)
477 {
478 switch (message->get_exchange_type(message))
479 {
480 case IKE_SA_INIT:
481 return get_nonce(message, &this->other_nonce);
482 case CREATE_CHILD_SA:
483 get_nonce(message, &this->other_nonce);
484 break;
485 default:
486 break;
487 }
488
489 process_payloads(this, message);
490
491 if (this->tsi == NULL || this->tsr == NULL)
492 {
493 DBG1(DBG_IKE, "TS payload missing in message");
494 return NEED_MORE;
495 }
496
497 this->policy = charon->policies->get_policy(charon->policies,
498 this->ike_sa->get_my_id(this->ike_sa),
499 this->ike_sa->get_other_id(this->ike_sa),
500 this->tsr, this->tsi,
501 this->ike_sa->get_my_host(this->ike_sa),
502 this->ike_sa->get_other_host(this->ike_sa));
503
504 if (this->policy && this->ike_sa->get_policy(this->ike_sa) == NULL)
505 {
506 this->ike_sa->set_policy(this->ike_sa, this->policy);
507 }
508
509 return NEED_MORE;
510 }
511
512 /**
513 * Implementation of task_t.build for responder
514 */
515 static status_t build_r(private_child_create_t *this, message_t *message)
516 {
517 switch (message->get_exchange_type(message))
518 {
519 case IKE_SA_INIT:
520 return get_nonce(message, &this->my_nonce);
521 case CREATE_CHILD_SA:
522 if (generate_nonce(&this->my_nonce) != SUCCESS)
523 {
524 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
525 return SUCCESS;
526 }
527 break;
528 default:
529 break;
530 }
531
532 if (this->policy == NULL)
533 {
534 SIG(CHILD_UP_FAILED, "received traffic selectors inacceptable");
535 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
536 return SUCCESS;
537 }
538
539 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
540 this->ike_sa->get_other_host(this->ike_sa),
541 this->ike_sa->get_my_id(this->ike_sa),
542 this->ike_sa->get_other_id(this->ike_sa),
543 this->policy, this->reqid,
544 this->ike_sa->is_natt_enabled(this->ike_sa));
545
546 if (select_and_install(this) != SUCCESS)
547 {
548 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
549 return SUCCESS;
550 }
551
552 build_payloads(this, message);
553
554 SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully");
555
556 return SUCCESS;
557 }
558
559 /**
560 * Implementation of task_t.process for initiator
561 */
562 static status_t process_i(private_child_create_t *this, message_t *message)
563 {
564 iterator_t *iterator;
565 payload_t *payload;
566 status_t status;
567
568 switch (message->get_exchange_type(message))
569 {
570 case IKE_SA_INIT:
571 return get_nonce(message, &this->other_nonce);
572 case CREATE_CHILD_SA:
573 get_nonce(message, &this->other_nonce);
574 break;
575 default:
576 break;
577 }
578
579 /* check for erronous notifies */
580 iterator = message->get_payload_iterator(message);
581 while (iterator->iterate(iterator, (void**)&payload))
582 {
583 if (payload->get_type(payload) == NOTIFY)
584 {
585 notify_payload_t *notify = (notify_payload_t*)payload;
586 notify_type_t type = notify->get_notify_type(notify);
587
588 if (type < 16383)
589 {
590 SIG(CHILD_UP_FAILED, "received %N notify error",
591 notify_type_names, type);
592 iterator->destroy(iterator);
593 /* an error in CHILD_SA creation is not critical */
594 return SUCCESS;
595 }
596 }
597 }
598 iterator->destroy(iterator);
599
600 process_payloads(this, message);
601
602 status = select_and_install(this);
603
604 SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully");
605
606 return SUCCESS;
607 }
608
609 /**
610 * Implementation of task_t.get_type
611 */
612 static task_type_t get_type(private_child_create_t *this)
613 {
614 return CHILD_CREATE;
615 }
616
617 /**
618 * Implementation of child_create_t.use_reqid
619 */
620 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
621 {
622 this->reqid = reqid;
623 }
624
625 /**
626 * Implementation of task_t.migrate
627 */
628 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
629 {
630 chunk_free(&this->my_nonce);
631 chunk_free(&this->other_nonce);
632 if (this->tsi)
633 {
634 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
635 }
636 if (this->tsr)
637 {
638 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
639 }
640 DESTROY_IF(this->child_sa);
641 DESTROY_IF(this->proposal);
642 if (this->proposals)
643 {
644 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
645 }
646
647 this->ike_sa = ike_sa;
648 this->proposals = NULL;
649 this->tsi = NULL;
650 this->tsr = NULL;
651 this->child_sa = NULL;
652 this->mode = MODE_TUNNEL;
653 this->reqid = 0;
654 }
655
656 /**
657 * Implementation of task_t.destroy
658 */
659 static void destroy(private_child_create_t *this)
660 {
661 chunk_free(&this->my_nonce);
662 chunk_free(&this->other_nonce);
663 if (this->tsi)
664 {
665 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
666 }
667 if (this->tsr)
668 {
669 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
670 }
671 DESTROY_IF(this->child_sa);
672 DESTROY_IF(this->proposal);
673 if (this->proposals)
674 {
675 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
676 }
677
678 DESTROY_IF(this->policy);
679 free(this);
680 }
681
682 /*
683 * Described in header.
684 */
685 child_create_t *child_create_create(ike_sa_t *ike_sa, policy_t *policy)
686 {
687 private_child_create_t *this = malloc_thing(private_child_create_t);
688
689 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
690 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
691 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
692 this->public.task.destroy = (void(*)(task_t*))destroy;
693 if (policy)
694 {
695 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
696 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
697 this->initiator = TRUE;
698 policy->get_ref(policy);
699 }
700 else
701 {
702 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
703 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
704 this->initiator = FALSE;
705 }
706
707 this->ike_sa = ike_sa;
708 this->policy = policy;
709 this->my_nonce = chunk_empty;
710 this->other_nonce = chunk_empty;
711 this->proposals = NULL;
712 this->proposal = NULL;
713 this->tsi = NULL;
714 this->tsr = NULL;
715 this->child_sa = NULL;
716 this->mode = MODE_TUNNEL;
717 this->reqid = 0;
718
719 return &this->public;
720 }