some task queueing improvements:
[strongswan.git] / src / charon / sa / tasks / child_create.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * $Id$
18 */
19
20 #include "child_create.h"
21
22 #include <daemon.h>
23 #include <crypto/diffie_hellman.h>
24 #include <encoding/payloads/sa_payload.h>
25 #include <encoding/payloads/ke_payload.h>
26 #include <encoding/payloads/ts_payload.h>
27 #include <encoding/payloads/nonce_payload.h>
28 #include <encoding/payloads/notify_payload.h>
29 #include <processing/jobs/delete_ike_sa_job.h>
30
31
32 typedef struct private_child_create_t private_child_create_t;
33
34 /**
35 * Private members of a child_create_t task.
36 */
37 struct private_child_create_t {
38
39 /**
40 * Public methods and task_t interface.
41 */
42 child_create_t public;
43
44 /**
45 * Assigned IKE_SA.
46 */
47 ike_sa_t *ike_sa;
48
49 /**
50 * Are we the initiator?
51 */
52 bool initiator;
53
54 /**
55 * nonce chosen by us
56 */
57 chunk_t my_nonce;
58
59 /**
60 * nonce chosen by peer
61 */
62 chunk_t other_nonce;
63
64 /**
65 * config to create the CHILD_SA from
66 */
67 child_cfg_t *config;
68
69 /**
70 * list of proposal candidates
71 */
72 linked_list_t *proposals;
73
74 /**
75 * selected proposal to use for CHILD_SA
76 */
77 proposal_t *proposal;
78
79 /**
80 * traffic selectors for initiators side
81 */
82 linked_list_t *tsi;
83
84 /**
85 * traffic selectors for responders side
86 */
87 linked_list_t *tsr;
88
89 /**
90 * optional diffie hellman exchange
91 */
92 diffie_hellman_t *dh;
93
94 /**
95 * group used for DH exchange
96 */
97 diffie_hellman_group_t dh_group;
98
99 /**
100 * IKE_SAs keymat
101 */
102 keymat_t *keymat;
103
104 /**
105 * mode the new CHILD_SA uses (transport/tunnel/beet)
106 */
107 ipsec_mode_t mode;
108
109 /**
110 * IPComp transform to use
111 */
112 ipcomp_transform_t ipcomp;
113
114 /**
115 * IPComp transform proposed or accepted by the other peer
116 */
117 ipcomp_transform_t ipcomp_received;
118
119 /**
120 * Own allocated SPI
121 */
122 u_int32_t my_spi;
123
124 /**
125 * SPI received in proposal
126 */
127 u_int32_t other_spi;
128
129 /**
130 * Own allocated Compression Parameter Index (CPI)
131 */
132 u_int16_t my_cpi;
133
134 /**
135 * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
136 */
137 u_int16_t other_cpi;
138
139 /**
140 * reqid to use if we are rekeying
141 */
142 u_int32_t reqid;
143
144 /**
145 * CHILD_SA which gets established
146 */
147 child_sa_t *child_sa;
148
149 /**
150 * successfully established the CHILD?
151 */
152 bool established;
153 };
154
155 /**
156 * get the nonce from a message
157 */
158 static status_t get_nonce(message_t *message, chunk_t *nonce)
159 {
160 nonce_payload_t *payload;
161
162 payload = (nonce_payload_t*)message->get_payload(message, NONCE);
163 if (payload == NULL)
164 {
165 return FAILED;
166 }
167 *nonce = payload->get_nonce(payload);
168 return NEED_MORE;
169 }
170
171 /**
172 * generate a new nonce to include in a CREATE_CHILD_SA message
173 */
174 static status_t generate_nonce(chunk_t *nonce)
175 {
176 rng_t *rng;
177
178 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
179 if (!rng)
180 {
181 DBG1(DBG_IKE, "error generating nonce value, no RNG found");
182 return FAILED;
183 }
184 rng->allocate_bytes(rng, NONCE_SIZE, nonce);
185 rng->destroy(rng);
186 return SUCCESS;
187 }
188
189 /**
190 * Check a list of traffic selectors if any selector belongs to host
191 */
192 static bool ts_list_is_host(linked_list_t *list, host_t *host)
193 {
194 traffic_selector_t *ts;
195 bool is_host = TRUE;
196 iterator_t *iterator = list->create_iterator(list, TRUE);
197
198 while (is_host && iterator->iterate(iterator, (void**)&ts))
199 {
200 is_host = is_host && ts->is_host(ts, host);
201 }
202 iterator->destroy(iterator);
203 return is_host;
204 }
205
206 /**
207 * Allocate SPIs and update proposals
208 */
209 static bool allocate_spi(private_child_create_t *this)
210 {
211 enumerator_t *enumerator;
212 proposal_t *proposal;
213
214 /* TODO: allocate additional SPI for AH if we have such proposals */
215 this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
216 if (this->my_spi)
217 {
218 if (this->initiator)
219 {
220 enumerator = this->proposals->create_enumerator(this->proposals);
221 while (enumerator->enumerate(enumerator, &proposal))
222 {
223 proposal->set_spi(proposal, this->my_spi);
224 }
225 enumerator->destroy(enumerator);
226 }
227 else
228 {
229 this->proposal->set_spi(this->proposal, this->my_spi);
230 }
231 return TRUE;
232 }
233 return FALSE;
234 }
235
236 /**
237 * Install a CHILD_SA for usage, return value:
238 * - FAILED: no acceptable proposal
239 * - INVALID_ARG: diffie hellman group inacceptable
240 * - NOT_FOUND: TS inacceptable
241 */
242 static status_t select_and_install(private_child_create_t *this, bool no_dh)
243 {
244 status_t status;
245 chunk_t nonce_i, nonce_r, encr_i, integ_i, encr_r, integ_r;
246 linked_list_t *my_ts, *other_ts;
247 host_t *me, *other, *other_vip, *my_vip;
248
249 if (this->proposals == NULL)
250 {
251 DBG1(DBG_IKE, "SA payload missing in message");
252 return FAILED;
253 }
254 if (this->tsi == NULL || this->tsr == NULL)
255 {
256 DBG1(DBG_IKE, "TS payloads missing in message");
257 return NOT_FOUND;
258 }
259
260 me = this->ike_sa->get_my_host(this->ike_sa);
261 other = this->ike_sa->get_other_host(this->ike_sa);
262 my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
263 other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
264
265 this->proposal = this->config->select_proposal(this->config, this->proposals,
266 no_dh);
267 if (this->proposal == NULL)
268 {
269 DBG1(DBG_IKE, "no acceptable proposal found");
270 return FAILED;
271 }
272 this->other_spi = this->proposal->get_spi(this->proposal);
273
274 if (!this->initiator && !allocate_spi(this))
275 { /* responder has no SPI allocated yet */
276 DBG1(DBG_IKE, "allocating SPI failed");
277 return FAILED;
278 }
279 this->child_sa->set_proposal(this->child_sa, this->proposal);
280
281 if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
282 {
283 u_int16_t group;
284
285 if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
286 &group, NULL))
287 {
288 DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
289 diffie_hellman_group_names, this->dh_group,
290 diffie_hellman_group_names, group);
291 this->dh_group = group;
292 return INVALID_ARG;
293 }
294 else
295 {
296 DBG1(DBG_IKE, "no acceptable proposal found");
297 return FAILED;
298 }
299 }
300
301 if (my_vip == NULL)
302 {
303 my_vip = me;
304 }
305 if (other_vip == NULL)
306 {
307 other_vip = other;
308 }
309
310 if (this->initiator)
311 {
312 nonce_i = this->my_nonce;
313 nonce_r = this->other_nonce;
314 my_ts = this->tsi;
315 other_ts = this->tsr;
316 }
317 else
318 {
319 nonce_r = this->my_nonce;
320 nonce_i = this->other_nonce;
321 my_ts = this->tsr;
322 other_ts = this->tsi;
323 }
324 my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
325 my_vip);
326 other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
327 other_vip);
328
329 if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
330 {
331 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
332 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
333 DBG1(DBG_IKE, "no acceptable traffic selectors found");
334 return NOT_FOUND;
335 }
336
337 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
338 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
339 if (this->initiator)
340 {
341 this->tsi = my_ts;
342 this->tsr = other_ts;
343 }
344 else
345 {
346 this->tsr = my_ts;
347 this->tsi = other_ts;
348 }
349
350 if (!this->initiator)
351 {
352 /* check if requested mode is acceptable, downgrade if required */
353 switch (this->mode)
354 {
355 case MODE_TRANSPORT:
356 if (!this->config->use_proxy_mode(this->config) &&
357 (!ts_list_is_host(this->tsi, other) ||
358 !ts_list_is_host(this->tsr, me))
359 )
360 {
361 this->mode = MODE_TUNNEL;
362 DBG1(DBG_IKE, "not using transport mode, not host-to-host");
363 }
364 else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
365 {
366 this->mode = MODE_TUNNEL;
367 DBG1(DBG_IKE, "not using transport mode, connection NATed");
368 }
369 break;
370 case MODE_BEET:
371 if (!ts_list_is_host(this->tsi, NULL) ||
372 !ts_list_is_host(this->tsr, NULL))
373 {
374 this->mode = MODE_TUNNEL;
375 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
376 }
377 break;
378 default:
379 break;
380 }
381 }
382
383 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
384 this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
385 this->child_sa->set_mode(this->child_sa, this->mode);
386 this->child_sa->set_protocol(this->child_sa,
387 this->proposal->get_protocol(this->proposal));
388
389 if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
390 {
391 this->my_cpi = this->other_cpi = 0;
392 this->ipcomp = IPCOMP_NONE;
393 }
394 status = FAILED;
395 if (this->keymat->derive_child_keys(this->keymat, this->proposal,
396 this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
397 {
398 if (this->initiator)
399 {
400 status = this->child_sa->install(this->child_sa, encr_r, integ_r,
401 this->my_spi, this->my_cpi, TRUE);
402 status = this->child_sa->install(this->child_sa, encr_i, integ_i,
403 this->other_spi, this->other_cpi, FALSE);
404 }
405 else
406 {
407 status = this->child_sa->install(this->child_sa, encr_i, integ_i,
408 this->my_spi, this->my_cpi, TRUE);
409 status = this->child_sa->install(this->child_sa, encr_r, integ_r,
410 this->other_spi, this->other_cpi, FALSE);
411 }
412 }
413 chunk_clear(&integ_i);
414 chunk_clear(&integ_r);
415 chunk_clear(&encr_i);
416 chunk_clear(&encr_r);
417
418 if (status != SUCCESS)
419 {
420 DBG1(DBG_IKE, "unable to install IPsec SA (SAD) in kernel");
421 return FAILED;
422 }
423
424 status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
425 if (status != SUCCESS)
426 {
427 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
428 return NOT_FOUND;
429 }
430
431 charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
432 nonce_i, nonce_r);
433
434 /* add to IKE_SA, and remove from task */
435 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
436 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
437 this->established = TRUE;
438 return SUCCESS;
439 }
440
441 /**
442 * build the payloads for the message
443 */
444 static void build_payloads(private_child_create_t *this, message_t *message)
445 {
446 sa_payload_t *sa_payload;
447 nonce_payload_t *nonce_payload;
448 ke_payload_t *ke_payload;
449 ts_payload_t *ts_payload;
450
451 /* add SA payload */
452 if (this->initiator)
453 {
454 sa_payload = sa_payload_create_from_proposal_list(this->proposals);
455 }
456 else
457 {
458 sa_payload = sa_payload_create_from_proposal(this->proposal);
459 }
460 message->add_payload(message, (payload_t*)sa_payload);
461
462 /* add nonce payload if not in IKE_AUTH */
463 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
464 {
465 nonce_payload = nonce_payload_create();
466 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
467 message->add_payload(message, (payload_t*)nonce_payload);
468 }
469
470 /* diffie hellman exchange, if PFS enabled */
471 if (this->dh)
472 {
473 ke_payload = ke_payload_create_from_diffie_hellman(this->dh);
474 message->add_payload(message, (payload_t*)ke_payload);
475 }
476
477 /* add TSi/TSr payloads */
478 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
479 message->add_payload(message, (payload_t*)ts_payload);
480 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
481 message->add_payload(message, (payload_t*)ts_payload);
482
483 /* add a notify if we are not in tunnel mode */
484 switch (this->mode)
485 {
486 case MODE_TRANSPORT:
487 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
488 break;
489 case MODE_BEET:
490 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
491 break;
492 default:
493 break;
494 }
495 }
496
497 /**
498 * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
499 */
500 static void add_ipcomp_notify(private_child_create_t *this,
501 message_t *message, u_int8_t ipcomp)
502 {
503 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
504 {
505 DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
506 "IPComp disabled");
507 return;
508 }
509
510 this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
511 if (this->my_cpi)
512 {
513 this->ipcomp = ipcomp;
514 message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
515 chunk_cata("cc", chunk_from_thing(this->my_cpi),
516 chunk_from_thing(ipcomp)));
517 }
518 else
519 {
520 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
521 }
522 }
523
524 /**
525 * handle a received notify payload
526 */
527 static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
528 {
529 switch (notify->get_notify_type(notify))
530 {
531 case USE_TRANSPORT_MODE:
532 this->mode = MODE_TRANSPORT;
533 break;
534 case USE_BEET_MODE:
535 this->mode = MODE_BEET;
536 break;
537 case IPCOMP_SUPPORTED:
538 {
539 ipcomp_transform_t ipcomp;
540 u_int16_t cpi;
541 chunk_t data;
542
543 data = notify->get_notification_data(notify);
544 cpi = *(u_int16_t*)data.ptr;
545 ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
546 switch (ipcomp)
547 {
548 case IPCOMP_DEFLATE:
549 this->other_cpi = cpi;
550 this->ipcomp_received = ipcomp;
551 break;
552 case IPCOMP_LZS:
553 case IPCOMP_LZJH:
554 default:
555 DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a "
556 "transform ID we don't support %N",
557 ipcomp_transform_names, ipcomp);
558 break;
559 }
560 }
561 default:
562 break;
563 }
564 }
565
566 /**
567 * Read payloads from message
568 */
569 static void process_payloads(private_child_create_t *this, message_t *message)
570 {
571 iterator_t *iterator;
572 payload_t *payload;
573 sa_payload_t *sa_payload;
574 ke_payload_t *ke_payload;
575 ts_payload_t *ts_payload;
576
577 /* defaults to TUNNEL mode */
578 this->mode = MODE_TUNNEL;
579
580 iterator = message->get_payload_iterator(message);
581 while (iterator->iterate(iterator, (void**)&payload))
582 {
583 switch (payload->get_type(payload))
584 {
585 case SECURITY_ASSOCIATION:
586 sa_payload = (sa_payload_t*)payload;
587 this->proposals = sa_payload->get_proposals(sa_payload);
588 break;
589 case KEY_EXCHANGE:
590 ke_payload = (ke_payload_t*)payload;
591 if (!this->initiator)
592 {
593 this->dh_group = ke_payload->get_dh_group_number(ke_payload);
594 this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
595 }
596 if (this->dh)
597 {
598 this->dh->set_other_public_value(this->dh,
599 ke_payload->get_key_exchange_data(ke_payload));
600 }
601 break;
602 case TRAFFIC_SELECTOR_INITIATOR:
603 ts_payload = (ts_payload_t*)payload;
604 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
605 break;
606 case TRAFFIC_SELECTOR_RESPONDER:
607 ts_payload = (ts_payload_t*)payload;
608 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
609 break;
610 case NOTIFY:
611 handle_notify(this, (notify_payload_t*)payload);
612 break;
613 default:
614 break;
615 }
616 }
617 iterator->destroy(iterator);
618 }
619
620 /**
621 * Implementation of task_t.build for initiator
622 */
623 static status_t build_i(private_child_create_t *this, message_t *message)
624 {
625 host_t *me, *other, *vip;
626 bool propose_all = FALSE;
627 peer_cfg_t *peer_cfg;
628
629 switch (message->get_exchange_type(message))
630 {
631 case IKE_SA_INIT:
632 return get_nonce(message, &this->my_nonce);
633 case CREATE_CHILD_SA:
634 if (generate_nonce(&this->my_nonce) != SUCCESS)
635 {
636 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
637 return SUCCESS;
638 }
639 if (this->dh_group == MODP_NONE)
640 {
641 this->dh_group = this->config->get_dh_group(this->config);
642 }
643 break;
644 case IKE_AUTH:
645 if (!message->get_payload(message, ID_INITIATOR))
646 {
647 /* send only in the first request, not in subsequent EAP */
648 return NEED_MORE;
649 }
650 break;
651 default:
652 break;
653 }
654
655 if (this->reqid)
656 {
657 DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
658 this->config->get_name(this->config), this->reqid);
659 }
660 else
661 {
662 DBG0(DBG_IKE, "establishing CHILD_SA %s",
663 this->config->get_name(this->config));
664 }
665
666 /* reuse virtual IP if we already have one */
667 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
668 if (me == NULL)
669 {
670 me = this->ike_sa->get_my_host(this->ike_sa);
671 }
672 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
673 if (other == NULL)
674 {
675 other = this->ike_sa->get_other_host(this->ike_sa);
676 }
677
678 /* check if we want a virtual IP, but don't have one */
679 if (!this->reqid)
680 {
681 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
682 vip = peer_cfg->get_virtual_ip(peer_cfg);
683 if (vip)
684 {
685 propose_all = TRUE;
686 }
687 }
688
689 if (propose_all)
690 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
691 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
692 NULL, NULL);
693 }
694 else
695 { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */
696 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
697 NULL, me);
698 }
699 this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
700 NULL, other);
701
702 this->proposals = this->config->get_proposals(this->config,
703 this->dh_group == MODP_NONE);
704 this->mode = this->config->get_mode(this->config);
705
706 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
707 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
708 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
709
710 if (!allocate_spi(this))
711 {
712 DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
713 return FAILED;
714 }
715
716 if (this->dh_group != MODP_NONE)
717 {
718 this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
719 }
720
721 if (this->config->use_ipcomp(this->config))
722 {
723 /* IPCOMP_DEFLATE is the only transform we support at the moment */
724 add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
725 }
726
727 build_payloads(this, message);
728
729 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
730 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
731 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
732 this->tsi = NULL;
733 this->tsr = NULL;
734 this->proposals = NULL;
735
736 return NEED_MORE;
737 }
738
739 /**
740 * Implementation of task_t.process for responder
741 */
742 static status_t process_r(private_child_create_t *this, message_t *message)
743 {
744 peer_cfg_t *peer_cfg;
745
746 switch (message->get_exchange_type(message))
747 {
748 case IKE_SA_INIT:
749 return get_nonce(message, &this->other_nonce);
750 case CREATE_CHILD_SA:
751 get_nonce(message, &this->other_nonce);
752 break;
753 case IKE_AUTH:
754 if (message->get_payload(message, ID_INITIATOR) == NULL)
755 {
756 /* wait until extensible authentication completed, if used */
757 return NEED_MORE;
758 }
759 default:
760 break;
761 }
762
763 process_payloads(this, message);
764
765 if (this->tsi == NULL || this->tsr == NULL)
766 {
767 DBG1(DBG_IKE, "TS payload missing in message");
768 return NEED_MORE;
769 }
770
771 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
772 if (peer_cfg)
773 {
774 host_t *me, *other;
775
776 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
777 if (me == NULL)
778 {
779 me = this->ike_sa->get_my_host(this->ike_sa);
780 }
781 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
782 if (other == NULL)
783 {
784 other = this->ike_sa->get_other_host(this->ike_sa);
785 }
786
787 this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
788 this->tsi, me, other);
789 }
790 return NEED_MORE;
791 }
792
793 /**
794 * handle CHILD_SA setup failure
795 */
796 static void handle_child_sa_failure(private_child_create_t *this,
797 message_t *message)
798 {
799 if (message->get_exchange_type(message) == IKE_AUTH &&
800 lib->settings->get_bool(lib->settings,
801 "charon.close_ike_on_child_failure", FALSE))
802 {
803 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
804 * first */
805 DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
806 charon->scheduler->schedule_job(charon->scheduler, (job_t*)
807 delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
808 100);
809 }
810 }
811
812 /**
813 * Implementation of task_t.build for responder
814 */
815 static status_t build_r(private_child_create_t *this, message_t *message)
816 {
817 payload_t *payload;
818 iterator_t *iterator;
819 bool no_dh = TRUE;
820
821 switch (message->get_exchange_type(message))
822 {
823 case IKE_SA_INIT:
824 return get_nonce(message, &this->my_nonce);
825 case CREATE_CHILD_SA:
826 if (generate_nonce(&this->my_nonce) != SUCCESS)
827 {
828 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
829 chunk_empty);
830 return SUCCESS;
831 }
832 no_dh = FALSE;
833 break;
834 case IKE_AUTH:
835 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
836 {
837 /* wait until extensible authentication completed, if used */
838 return NEED_MORE;
839 }
840 default:
841 break;
842 }
843
844 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
845 {
846 DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
847 message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
848 return SUCCESS;
849 }
850
851 if (this->config == NULL)
852 {
853 DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
854 this->tsr, this->tsi);
855 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
856 handle_child_sa_failure(this, message);
857 return SUCCESS;
858 }
859
860 /* check if ike_config_t included non-critical error notifies */
861 iterator = message->get_payload_iterator(message);
862 while (iterator->iterate(iterator, (void**)&payload))
863 {
864 if (payload->get_type(payload) == NOTIFY)
865 {
866 notify_payload_t *notify = (notify_payload_t*)payload;
867
868 switch (notify->get_notify_type(notify))
869 {
870 case INTERNAL_ADDRESS_FAILURE:
871 case FAILED_CP_REQUIRED:
872 {
873 DBG1(DBG_IKE,"configuration payload negotation "
874 "failed, no CHILD_SA built");
875 iterator->destroy(iterator);
876 handle_child_sa_failure(this, message);
877 return SUCCESS;
878 }
879 default:
880 break;
881 }
882 }
883 }
884 iterator->destroy(iterator);
885
886 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
887 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
888 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
889
890 if (this->ipcomp_received != IPCOMP_NONE)
891 {
892 if (this->config->use_ipcomp(this->config))
893 {
894 add_ipcomp_notify(this, message, this->ipcomp_received);
895 }
896 else
897 {
898 DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
899 notify_type_names, IPCOMP_SUPPORTED);
900 }
901 }
902
903 switch (select_and_install(this, no_dh))
904 {
905 case SUCCESS:
906 break;
907 case NOT_FOUND:
908 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
909 handle_child_sa_failure(this, message);
910 return SUCCESS;
911 case INVALID_ARG:
912 {
913 u_int16_t group = htons(this->dh_group);
914 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
915 chunk_from_thing(group));
916 handle_child_sa_failure(this, message);
917 return SUCCESS;
918 }
919 case FAILED:
920 default:
921 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
922 handle_child_sa_failure(this, message);
923 return SUCCESS;
924 }
925
926 build_payloads(this, message);
927
928 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
929 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
930 this->child_sa->get_name(this->child_sa),
931 this->child_sa->get_reqid(this->child_sa),
932 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
933 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
934 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
935 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
936
937 return SUCCESS;
938 }
939
940 /**
941 * Implementation of task_t.process for initiator
942 */
943 static status_t process_i(private_child_create_t *this, message_t *message)
944 {
945 iterator_t *iterator;
946 payload_t *payload;
947 bool no_dh = TRUE;
948
949 switch (message->get_exchange_type(message))
950 {
951 case IKE_SA_INIT:
952 return get_nonce(message, &this->other_nonce);
953 case CREATE_CHILD_SA:
954 get_nonce(message, &this->other_nonce);
955 no_dh = FALSE;
956 break;
957 case IKE_AUTH:
958 if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
959 {
960 /* wait until extensible authentication completed, if used */
961 return NEED_MORE;
962 }
963 default:
964 break;
965 }
966
967 /* check for erronous notifies */
968 iterator = message->get_payload_iterator(message);
969 while (iterator->iterate(iterator, (void**)&payload))
970 {
971 if (payload->get_type(payload) == NOTIFY)
972 {
973 notify_payload_t *notify = (notify_payload_t*)payload;
974 notify_type_t type = notify->get_notify_type(notify);
975
976 switch (type)
977 {
978 /* handle notify errors related to CHILD_SA only */
979 case NO_PROPOSAL_CHOSEN:
980 case SINGLE_PAIR_REQUIRED:
981 case NO_ADDITIONAL_SAS:
982 case INTERNAL_ADDRESS_FAILURE:
983 case FAILED_CP_REQUIRED:
984 case TS_UNACCEPTABLE:
985 case INVALID_SELECTORS:
986 {
987 DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
988 notify_type_names, type);
989 iterator->destroy(iterator);
990 handle_child_sa_failure(this, message);
991 /* an error in CHILD_SA creation is not critical */
992 return SUCCESS;
993 }
994 case INVALID_KE_PAYLOAD:
995 {
996 chunk_t data;
997 diffie_hellman_group_t bad_group;
998
999 bad_group = this->dh_group;
1000 data = notify->get_notification_data(notify);
1001 this->dh_group = ntohs(*((u_int16_t*)data.ptr));
1002 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
1003 "it requested %N", diffie_hellman_group_names,
1004 bad_group, diffie_hellman_group_names, this->dh_group);
1005
1006 this->public.task.migrate(&this->public.task, this->ike_sa);
1007 iterator->destroy(iterator);
1008 return NEED_MORE;
1009 }
1010 default:
1011 break;
1012 }
1013 }
1014 }
1015 iterator->destroy(iterator);
1016
1017 process_payloads(this, message);
1018
1019 if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
1020 {
1021 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
1022 " one, no CHILD_SA built");
1023 handle_child_sa_failure(this, message);
1024 return SUCCESS;
1025 }
1026 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
1027 {
1028 DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
1029 "IPComp is disabled");
1030 this->ipcomp = IPCOMP_NONE;
1031 }
1032 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
1033 {
1034 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1035 "no CHILD_SA built");
1036 handle_child_sa_failure(this, message);
1037 return SUCCESS;
1038 }
1039
1040 if (select_and_install(this, no_dh) == SUCCESS)
1041 {
1042 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
1043 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1044 this->child_sa->get_name(this->child_sa),
1045 this->child_sa->get_reqid(this->child_sa),
1046 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
1047 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
1048 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
1049 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
1050 }
1051 else
1052 {
1053 handle_child_sa_failure(this, message);
1054 }
1055 return SUCCESS;
1056 }
1057
1058 /**
1059 * Implementation of task_t.get_type
1060 */
1061 static task_type_t get_type(private_child_create_t *this)
1062 {
1063 return CHILD_CREATE;
1064 }
1065
1066 /**
1067 * Implementation of child_create_t.use_reqid
1068 */
1069 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
1070 {
1071 this->reqid = reqid;
1072 }
1073
1074 /**
1075 * Implementation of child_create_t.get_child
1076 */
1077 static child_sa_t* get_child(private_child_create_t *this)
1078 {
1079 return this->child_sa;
1080 }
1081
1082 /**
1083 * Implementation of child_create_t.get_lower_nonce
1084 */
1085 static chunk_t get_lower_nonce(private_child_create_t *this)
1086 {
1087 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1088 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1089 {
1090 return this->my_nonce;
1091 }
1092 else
1093 {
1094 return this->other_nonce;
1095 }
1096 }
1097
1098 /**
1099 * Implementation of task_t.migrate
1100 */
1101 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
1102 {
1103 chunk_free(&this->my_nonce);
1104 chunk_free(&this->other_nonce);
1105 if (this->tsi)
1106 {
1107 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1108 }
1109 if (this->tsr)
1110 {
1111 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1112 }
1113 DESTROY_IF(this->child_sa);
1114 DESTROY_IF(this->proposal);
1115 DESTROY_IF(this->dh);
1116 if (this->proposals)
1117 {
1118 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1119 }
1120
1121 this->ike_sa = ike_sa;
1122 this->keymat = ike_sa->get_keymat(ike_sa);
1123 this->proposal = NULL;
1124 this->proposals = NULL;
1125 this->tsi = NULL;
1126 this->tsr = NULL;
1127 this->dh = NULL;
1128 this->child_sa = NULL;
1129 this->mode = MODE_TUNNEL;
1130 this->ipcomp = IPCOMP_NONE;
1131 this->ipcomp_received = IPCOMP_NONE;
1132 this->other_cpi = 0;
1133 this->reqid = 0;
1134 this->established = FALSE;
1135 }
1136
1137 /**
1138 * Implementation of task_t.destroy
1139 */
1140 static void destroy(private_child_create_t *this)
1141 {
1142 chunk_free(&this->my_nonce);
1143 chunk_free(&this->other_nonce);
1144 if (this->tsi)
1145 {
1146 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1147 }
1148 if (this->tsr)
1149 {
1150 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1151 }
1152 if (!this->established)
1153 {
1154 DESTROY_IF(this->child_sa);
1155 }
1156 DESTROY_IF(this->proposal);
1157 DESTROY_IF(this->dh);
1158 if (this->proposals)
1159 {
1160 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1161 }
1162
1163 DESTROY_IF(this->config);
1164 free(this);
1165 }
1166
1167 /*
1168 * Described in header.
1169 */
1170 child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
1171 {
1172 private_child_create_t *this = malloc_thing(private_child_create_t);
1173
1174 this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
1175 this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
1176 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
1177 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
1178 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
1179 this->public.task.destroy = (void(*)(task_t*))destroy;
1180 if (config)
1181 {
1182 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
1183 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
1184 this->initiator = TRUE;
1185 config->get_ref(config);
1186 }
1187 else
1188 {
1189 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
1190 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1191 this->initiator = FALSE;
1192 }
1193
1194 this->ike_sa = ike_sa;
1195 this->config = config;
1196 this->my_nonce = chunk_empty;
1197 this->other_nonce = chunk_empty;
1198 this->proposals = NULL;
1199 this->proposal = NULL;
1200 this->tsi = NULL;
1201 this->tsr = NULL;
1202 this->dh = NULL;
1203 this->dh_group = MODP_NONE;
1204 this->keymat = ike_sa->get_keymat(ike_sa);
1205 this->child_sa = NULL;
1206 this->mode = MODE_TUNNEL;
1207 this->ipcomp = IPCOMP_NONE;
1208 this->ipcomp_received = IPCOMP_NONE;
1209 this->my_spi = 0;
1210 this->other_spi = 0;
1211 this->my_cpi = 0;
1212 this->other_cpi = 0;
1213 this->reqid = 0;
1214 this->established = FALSE;
1215
1216 return &this->public;
1217 }