fixed notify handling in IKE_AUTH
[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->proposal == NULL)
199 {
200 SIG(CHILD_UP_FAILED, "no acceptable proposal found");
201 return FAILED;
202 }
203
204 if (this->initiator && my_vip)
205 { /* if we have a virtual IP, shorten our TS to the minimum */
206 my_ts = this->policy->select_my_traffic_selectors(this->policy, my_ts,
207 my_vip);
208 /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
209 this->child_sa->set_virtual_ip(this->child_sa, my_vip);
210 }
211 else
212 { /* shorten in the host2host case only */
213 my_ts = this->policy->select_my_traffic_selectors(this->policy,
214 my_ts, me);
215 }
216 if (other_vip)
217 { /* if other has a virtual IP, shorten it's traffic selectors to it */
218 other_ts = this->policy->select_other_traffic_selectors(this->policy,
219 other_ts, other_vip);
220 }
221 else
222 { /* use his host for the host2host case */
223 other_ts = this->policy->select_other_traffic_selectors(this->policy,
224 other_ts, other);
225 }
226 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
227 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
228 if (this->initiator)
229 {
230 this->tsi = my_ts;
231 this->tsr = other_ts;
232 }
233 else
234 {
235 this->tsr = my_ts;
236 this->tsi = other_ts;
237 }
238
239 if (this->tsi->get_count(this->tsi) == 0 ||
240 this->tsr->get_count(this->tsr) == 0)
241 {
242 SIG(CHILD_UP_FAILED, "no acceptable traffic selectors found");
243 return FAILED;
244 }
245
246 if (!this->initiator)
247 {
248 /* check if requested mode is acceptable, downgrade if required */
249 switch (this->mode)
250 {
251 case MODE_TRANSPORT:
252 if (!ts_list_is_host(this->tsi, other) ||
253 !ts_list_is_host(this->tsr, me))
254 {
255 this->mode = MODE_TUNNEL;
256 DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
257 }
258 else if (this->ike_sa->is_natt_enabled(this->ike_sa))
259 {
260 this->mode = MODE_TUNNEL;
261 DBG1(DBG_IKE, "not using tranport mode, connection NATed");
262 }
263 break;
264 case MODE_BEET:
265 if (!ts_list_is_host(this->tsi, NULL) ||
266 !ts_list_is_host(this->tsr, NULL))
267 {
268 this->mode = MODE_TUNNEL;
269 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
270 }
271 break;
272 default:
273 break;
274 }
275 }
276
277 seed = chunk_cata("cc", nonce_i, nonce_r);
278 prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
279
280 if (this->initiator)
281 {
282 status = this->child_sa->update(this->child_sa, this->proposal,
283 this->mode, prf_plus);
284 }
285 else
286 {
287 status = this->child_sa->add(this->child_sa, this->proposal,
288 this->mode, prf_plus);
289 }
290 prf_plus->destroy(prf_plus);
291
292 if (status != SUCCESS)
293 {
294 SIG(CHILD_UP_FAILED, "unable to install IPsec SA (SAD) in kernel");
295 return status;
296 }
297
298 status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
299 this->mode);
300
301 if (status != SUCCESS)
302 {
303 SIG(CHILD_UP_FAILED, "unable to install IPsec policies (SPD) in kernel");
304 return status;
305 }
306 /* add to IKE_SA, and remove from task */
307 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
308 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
309 this->child_sa = NULL;
310 return SUCCESS;
311 }
312
313 /**
314 * build the payloads for the message
315 */
316 static void build_payloads(private_child_create_t *this, message_t *message)
317 {
318 sa_payload_t *sa_payload;
319 ts_payload_t *ts_payload;
320 nonce_payload_t *nonce_payload;
321
322 /* add SA payload */
323 if (this->initiator)
324 {
325 sa_payload = sa_payload_create_from_proposal_list(this->proposals);
326 }
327 else
328 {
329 sa_payload = sa_payload_create_from_proposal(this->proposal);
330 }
331 message->add_payload(message, (payload_t*)sa_payload);
332
333 /* add nonce payload if not in IKE_AUTH */
334 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
335 {
336 nonce_payload = nonce_payload_create();
337 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
338 message->add_payload(message, (payload_t*)nonce_payload);
339 }
340
341 /* add TSi/TSr payloads */
342 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
343 message->add_payload(message, (payload_t*)ts_payload);
344 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
345 message->add_payload(message, (payload_t*)ts_payload);
346
347 /* add a notify if we are not in tunnel mode */
348 switch (this->mode)
349 {
350 case MODE_TRANSPORT:
351 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
352 break;
353 case MODE_BEET:
354 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
355 break;
356 default:
357 break;
358 }
359 }
360
361 /**
362 * Read payloads from message
363 */
364 static void process_payloads(private_child_create_t *this, message_t *message)
365 {
366 iterator_t *iterator;
367 payload_t *payload;
368 sa_payload_t *sa_payload;
369 ts_payload_t *ts_payload;
370 notify_payload_t *notify_payload;
371
372 /* defaults to TUNNEL mode */
373 this->mode = MODE_TUNNEL;
374
375 iterator = message->get_payload_iterator(message);
376 while (iterator->iterate(iterator, (void**)&payload))
377 {
378 switch (payload->get_type(payload))
379 {
380 case SECURITY_ASSOCIATION:
381 sa_payload = (sa_payload_t*)payload;
382 this->proposals = sa_payload->get_proposals(sa_payload);
383 break;
384 case TRAFFIC_SELECTOR_INITIATOR:
385 ts_payload = (ts_payload_t*)payload;
386 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
387 break;
388 case TRAFFIC_SELECTOR_RESPONDER:
389 ts_payload = (ts_payload_t*)payload;
390 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
391 break;
392 case NOTIFY:
393 notify_payload = (notify_payload_t*)payload;
394 switch (notify_payload ->get_notify_type(notify_payload ))
395 {
396 case USE_TRANSPORT_MODE:
397 this->mode = MODE_TRANSPORT;
398 break;
399 case USE_BEET_MODE:
400 this->mode = MODE_BEET;
401 break;
402 default:
403 break;
404 }
405 break;
406 default:
407 break;
408 }
409 }
410 iterator->destroy(iterator);
411 }
412
413 /**
414 * Implementation of task_t.build for initiator
415 */
416 static status_t build_i(private_child_create_t *this, message_t *message)
417 {
418 host_t *me, *other, *vip;
419
420 switch (message->get_exchange_type(message))
421 {
422 case IKE_SA_INIT:
423 return get_nonce(message, &this->my_nonce);
424 case CREATE_CHILD_SA:
425 if (generate_nonce(&this->my_nonce) != SUCCESS)
426 {
427 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
428 return SUCCESS;
429 }
430 break;
431 default:
432 break;
433 }
434
435 SIG(CHILD_UP_START, "establishing CHILD_SA");
436
437 me = this->ike_sa->get_my_host(this->ike_sa);
438 other = this->ike_sa->get_other_host(this->ike_sa);
439 vip = this->policy->get_virtual_ip(this->policy, NULL);
440
441 if (vip)
442 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
443 this->tsi = this->policy->get_my_traffic_selectors(this->policy, NULL);
444 vip->destroy(vip);
445 }
446 else
447 { /* but shorten a 0.0.0.0/0 subnet to the actual address if host2host */
448 this->tsi = this->policy->get_my_traffic_selectors(this->policy, me);
449 }
450 this->tsr = this->policy->get_other_traffic_selectors(this->policy, other);
451 this->proposals = this->policy->get_proposals(this->policy);
452 this->mode = this->policy->get_mode(this->policy);
453
454 this->child_sa = child_sa_create(me, other,
455 this->ike_sa->get_my_id(this->ike_sa),
456 this->ike_sa->get_other_id(this->ike_sa),
457 this->policy, this->reqid,
458 this->ike_sa->is_natt_enabled(this->ike_sa));
459
460 if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
461 {
462 SIG(CHILD_UP_FAILED, "unable to allocate SPIs from kernel");
463 return FAILED;
464 }
465
466 build_payloads(this, message);
467
468 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
469 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
470 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
471 this->tsi = NULL;
472 this->tsr = NULL;
473 this->proposals = NULL;
474
475 return NEED_MORE;
476 }
477
478 /**
479 * Implementation of task_t.process for initiator
480 */
481 static status_t process_r(private_child_create_t *this, message_t *message)
482 {
483 switch (message->get_exchange_type(message))
484 {
485 case IKE_SA_INIT:
486 return get_nonce(message, &this->other_nonce);
487 case CREATE_CHILD_SA:
488 get_nonce(message, &this->other_nonce);
489 break;
490 default:
491 break;
492 }
493
494 process_payloads(this, message);
495
496 if (this->tsi == NULL || this->tsr == NULL)
497 {
498 DBG1(DBG_IKE, "TS payload missing in message");
499 return NEED_MORE;
500 }
501
502 this->policy = charon->policies->get_policy(charon->policies,
503 this->ike_sa->get_my_id(this->ike_sa),
504 this->ike_sa->get_other_id(this->ike_sa),
505 this->tsr, this->tsi,
506 this->ike_sa->get_my_host(this->ike_sa),
507 this->ike_sa->get_other_host(this->ike_sa));
508
509 if (this->policy && this->ike_sa->get_policy(this->ike_sa) == NULL)
510 {
511 this->ike_sa->set_policy(this->ike_sa, this->policy);
512 }
513
514 return NEED_MORE;
515 }
516
517 /**
518 * Implementation of task_t.build for responder
519 */
520 static status_t build_r(private_child_create_t *this, message_t *message)
521 {
522 switch (message->get_exchange_type(message))
523 {
524 case IKE_SA_INIT:
525 return get_nonce(message, &this->my_nonce);
526 case CREATE_CHILD_SA:
527 if (generate_nonce(&this->my_nonce) != SUCCESS)
528 {
529 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
530 return SUCCESS;
531 }
532 break;
533 default:
534 break;
535 }
536
537 if (this->policy == NULL)
538 {
539 SIG(CHILD_UP_FAILED, "received traffic selectors inacceptable");
540 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
541 return SUCCESS;
542 }
543
544 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
545 this->ike_sa->get_other_host(this->ike_sa),
546 this->ike_sa->get_my_id(this->ike_sa),
547 this->ike_sa->get_other_id(this->ike_sa),
548 this->policy, this->reqid,
549 this->ike_sa->is_natt_enabled(this->ike_sa));
550
551 if (select_and_install(this) != SUCCESS)
552 {
553 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
554 return SUCCESS;
555 }
556
557 build_payloads(this, message);
558
559 SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully");
560
561 return SUCCESS;
562 }
563
564 /**
565 * Implementation of task_t.process for initiator
566 */
567 static status_t process_i(private_child_create_t *this, message_t *message)
568 {
569 iterator_t *iterator;
570 payload_t *payload;
571 status_t status;
572
573 switch (message->get_exchange_type(message))
574 {
575 case IKE_SA_INIT:
576 return get_nonce(message, &this->other_nonce);
577 case CREATE_CHILD_SA:
578 get_nonce(message, &this->other_nonce);
579 break;
580 default:
581 break;
582 }
583
584 /* check for erronous notifies */
585 iterator = message->get_payload_iterator(message);
586 while (iterator->iterate(iterator, (void**)&payload))
587 {
588 if (payload->get_type(payload) == NOTIFY)
589 {
590 notify_payload_t *notify = (notify_payload_t*)payload;
591 notify_type_t type = notify->get_notify_type(notify);
592
593 switch (type)
594 {
595 /* handle notify errors related to CHILD_SA only */
596 case NO_PROPOSAL_CHOSEN:
597 case SINGLE_PAIR_REQUIRED:
598 case NO_ADDITIONAL_SAS:
599 case INTERNAL_ADDRESS_FAILURE:
600 case FAILED_CP_REQUIRED:
601 case TS_UNACCEPTABLE:
602 case INVALID_SELECTORS:
603 {
604 SIG(CHILD_UP_FAILED, "received %N notify, no CHILD_SA built",
605 notify_type_names, type);
606 iterator->destroy(iterator);
607 /* an error in CHILD_SA creation is not critical */
608 return SUCCESS;
609 }
610 default:
611 break;
612 }
613 }
614 }
615 iterator->destroy(iterator);
616
617 process_payloads(this, message);
618
619 status = select_and_install(this);
620
621 SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully");
622
623 return SUCCESS;
624 }
625
626 /**
627 * Implementation of task_t.get_type
628 */
629 static task_type_t get_type(private_child_create_t *this)
630 {
631 return CHILD_CREATE;
632 }
633
634 /**
635 * Implementation of child_create_t.use_reqid
636 */
637 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
638 {
639 this->reqid = reqid;
640 }
641
642 /**
643 * Implementation of task_t.migrate
644 */
645 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
646 {
647 chunk_free(&this->my_nonce);
648 chunk_free(&this->other_nonce);
649 if (this->tsi)
650 {
651 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
652 }
653 if (this->tsr)
654 {
655 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
656 }
657 DESTROY_IF(this->child_sa);
658 DESTROY_IF(this->proposal);
659 if (this->proposals)
660 {
661 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
662 }
663
664 this->ike_sa = ike_sa;
665 this->proposals = NULL;
666 this->tsi = NULL;
667 this->tsr = NULL;
668 this->child_sa = NULL;
669 this->mode = MODE_TUNNEL;
670 this->reqid = 0;
671 }
672
673 /**
674 * Implementation of task_t.destroy
675 */
676 static void destroy(private_child_create_t *this)
677 {
678 chunk_free(&this->my_nonce);
679 chunk_free(&this->other_nonce);
680 if (this->tsi)
681 {
682 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
683 }
684 if (this->tsr)
685 {
686 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
687 }
688 DESTROY_IF(this->child_sa);
689 DESTROY_IF(this->proposal);
690 if (this->proposals)
691 {
692 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
693 }
694
695 DESTROY_IF(this->policy);
696 free(this);
697 }
698
699 /*
700 * Described in header.
701 */
702 child_create_t *child_create_create(ike_sa_t *ike_sa, policy_t *policy)
703 {
704 private_child_create_t *this = malloc_thing(private_child_create_t);
705
706 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
707 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
708 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
709 this->public.task.destroy = (void(*)(task_t*))destroy;
710 if (policy)
711 {
712 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
713 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
714 this->initiator = TRUE;
715 policy->get_ref(policy);
716 }
717 else
718 {
719 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
720 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
721 this->initiator = FALSE;
722 }
723
724 this->ike_sa = ike_sa;
725 this->policy = policy;
726 this->my_nonce = chunk_empty;
727 this->other_nonce = chunk_empty;
728 this->proposals = NULL;
729 this->proposal = NULL;
730 this->tsi = NULL;
731 this->tsr = NULL;
732 this->child_sa = NULL;
733 this->mode = MODE_TUNNEL;
734 this->reqid = 0;
735
736 return &this->public;
737 }