fixed cleanup of traffic selector lists
[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
18 #include "child_create.h"
19
20 #include <daemon.h>
21 #include <crypto/diffie_hellman.h>
22 #include <encoding/payloads/sa_payload.h>
23 #include <encoding/payloads/ke_payload.h>
24 #include <encoding/payloads/ts_payload.h>
25 #include <encoding/payloads/nonce_payload.h>
26 #include <encoding/payloads/notify_payload.h>
27 #include <processing/jobs/delete_ike_sa_job.h>
28
29
30 typedef struct private_child_create_t private_child_create_t;
31
32 /**
33 * Private members of a child_create_t task.
34 */
35 struct private_child_create_t {
36
37 /**
38 * Public methods and task_t interface.
39 */
40 child_create_t public;
41
42 /**
43 * Assigned IKE_SA.
44 */
45 ike_sa_t *ike_sa;
46
47 /**
48 * Are we the initiator?
49 */
50 bool initiator;
51
52 /**
53 * nonce chosen by us
54 */
55 chunk_t my_nonce;
56
57 /**
58 * nonce chosen by peer
59 */
60 chunk_t other_nonce;
61
62 /**
63 * config to create the CHILD_SA from
64 */
65 child_cfg_t *config;
66
67 /**
68 * list of proposal candidates
69 */
70 linked_list_t *proposals;
71
72 /**
73 * selected proposal to use for CHILD_SA
74 */
75 proposal_t *proposal;
76
77 /**
78 * traffic selectors for initiators side
79 */
80 linked_list_t *tsi;
81
82 /**
83 * traffic selectors for responders side
84 */
85 linked_list_t *tsr;
86
87 /**
88 * optional diffie hellman exchange
89 */
90 diffie_hellman_t *dh;
91
92 /**
93 * group used for DH exchange
94 */
95 diffie_hellman_group_t dh_group;
96
97 /**
98 * IKE_SAs keymat
99 */
100 keymat_t *keymat;
101
102 /**
103 * mode the new CHILD_SA uses (transport/tunnel/beet)
104 */
105 ipsec_mode_t mode;
106
107 /**
108 * IPComp transform to use
109 */
110 ipcomp_transform_t ipcomp;
111
112 /**
113 * IPComp transform proposed or accepted by the other peer
114 */
115 ipcomp_transform_t ipcomp_received;
116
117 /**
118 * Own allocated SPI
119 */
120 u_int32_t my_spi;
121
122 /**
123 * SPI received in proposal
124 */
125 u_int32_t other_spi;
126
127 /**
128 * Own allocated Compression Parameter Index (CPI)
129 */
130 u_int16_t my_cpi;
131
132 /**
133 * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
134 */
135 u_int16_t other_cpi;
136
137 /**
138 * reqid to use if we are rekeying
139 */
140 u_int32_t reqid;
141
142 /**
143 * CHILD_SA which gets established
144 */
145 child_sa_t *child_sa;
146
147 /**
148 * successfully established the CHILD?
149 */
150 bool established;
151 };
152
153 /**
154 * get the nonce from a message
155 */
156 static status_t get_nonce(message_t *message, chunk_t *nonce)
157 {
158 nonce_payload_t *payload;
159
160 payload = (nonce_payload_t*)message->get_payload(message, NONCE);
161 if (payload == NULL)
162 {
163 return FAILED;
164 }
165 *nonce = payload->get_nonce(payload);
166 return NEED_MORE;
167 }
168
169 /**
170 * generate a new nonce to include in a CREATE_CHILD_SA message
171 */
172 static status_t generate_nonce(chunk_t *nonce)
173 {
174 rng_t *rng;
175
176 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
177 if (!rng)
178 {
179 DBG1(DBG_IKE, "error generating nonce value, no RNG found");
180 return FAILED;
181 }
182 rng->allocate_bytes(rng, NONCE_SIZE, nonce);
183 rng->destroy(rng);
184 return SUCCESS;
185 }
186
187 /**
188 * Check a list of traffic selectors if any selector belongs to host
189 */
190 static bool ts_list_is_host(linked_list_t *list, host_t *host)
191 {
192 traffic_selector_t *ts;
193 bool is_host = TRUE;
194 iterator_t *iterator = list->create_iterator(list, TRUE);
195
196 while (is_host && iterator->iterate(iterator, (void**)&ts))
197 {
198 is_host = is_host && ts->is_host(ts, host);
199 }
200 iterator->destroy(iterator);
201 return is_host;
202 }
203
204 /**
205 * Allocate SPIs and update proposals
206 */
207 static bool allocate_spi(private_child_create_t *this)
208 {
209 enumerator_t *enumerator;
210 proposal_t *proposal;
211
212 /* TODO: allocate additional SPI for AH if we have such proposals */
213 this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
214 if (this->my_spi)
215 {
216 if (this->initiator)
217 {
218 enumerator = this->proposals->create_enumerator(this->proposals);
219 while (enumerator->enumerate(enumerator, &proposal))
220 {
221 proposal->set_spi(proposal, this->my_spi);
222 }
223 enumerator->destroy(enumerator);
224 }
225 else
226 {
227 this->proposal->set_spi(this->proposal, this->my_spi);
228 }
229 return TRUE;
230 }
231 return FALSE;
232 }
233
234 /**
235 * Install a CHILD_SA for usage, return value:
236 * - FAILED: no acceptable proposal
237 * - INVALID_ARG: diffie hellman group inacceptable
238 * - NOT_FOUND: TS inacceptable
239 */
240 static status_t select_and_install(private_child_create_t *this, bool no_dh)
241 {
242 status_t status;
243 chunk_t nonce_i, nonce_r;
244 chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
245 chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
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 enumerator_t *enumerator;
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 enumerator = message->create_payload_enumerator(message);
581 while (enumerator->enumerate(enumerator, &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 enumerator->destroy(enumerator);
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 peer_cfg_t *peer_cfg;
627
628 switch (message->get_exchange_type(message))
629 {
630 case IKE_SA_INIT:
631 return get_nonce(message, &this->my_nonce);
632 case CREATE_CHILD_SA:
633 if (generate_nonce(&this->my_nonce) != SUCCESS)
634 {
635 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
636 return SUCCESS;
637 }
638 if (this->dh_group == MODP_NONE)
639 {
640 this->dh_group = this->config->get_dh_group(this->config);
641 }
642 break;
643 case IKE_AUTH:
644 if (message->get_message_id(message) != 1)
645 {
646 /* send only in the first request, not in subsequent rounds */
647 return NEED_MORE;
648 }
649 break;
650 default:
651 break;
652 }
653
654 if (this->reqid)
655 {
656 DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
657 this->config->get_name(this->config), this->reqid);
658 }
659 else
660 {
661 DBG0(DBG_IKE, "establishing CHILD_SA %s",
662 this->config->get_name(this->config));
663 }
664
665 /* reuse virtual IP if we already have one */
666 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
667 if (me == NULL)
668 {
669 me = this->ike_sa->get_my_host(this->ike_sa);
670 }
671 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
672 if (other == NULL)
673 {
674 other = this->ike_sa->get_other_host(this->ike_sa);
675 }
676
677 /* check if we want a virtual IP, but don't have one */
678 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
679 vip = peer_cfg->get_virtual_ip(peer_cfg);
680 if (!this->reqid && vip)
681 {
682 /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
683 vip = host_create_any(vip->get_family(vip));
684 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
685 NULL, vip);
686 vip->destroy(vip);
687 }
688 else
689 { /* but narrow it for host2host / if we already have a vip */
690 this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
691 NULL, me);
692 }
693 this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
694 NULL, other);
695
696 this->proposals = this->config->get_proposals(this->config,
697 this->dh_group == MODP_NONE);
698 this->mode = this->config->get_mode(this->config);
699
700 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
701 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
702 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
703
704 if (!allocate_spi(this))
705 {
706 DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
707 return FAILED;
708 }
709
710 if (this->dh_group != MODP_NONE)
711 {
712 this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
713 }
714
715 if (this->config->use_ipcomp(this->config))
716 {
717 /* IPCOMP_DEFLATE is the only transform we support at the moment */
718 add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
719 }
720
721 build_payloads(this, message);
722
723 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
724 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
725 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
726 this->tsi = NULL;
727 this->tsr = NULL;
728 this->proposals = NULL;
729
730 return NEED_MORE;
731 }
732
733 /**
734 * Implementation of task_t.process for responder
735 */
736 static status_t process_r(private_child_create_t *this, message_t *message)
737 {
738 switch (message->get_exchange_type(message))
739 {
740 case IKE_SA_INIT:
741 return get_nonce(message, &this->other_nonce);
742 case CREATE_CHILD_SA:
743 get_nonce(message, &this->other_nonce);
744 break;
745 case IKE_AUTH:
746 if (message->get_message_id(message) != 1)
747 {
748 /* only handle first AUTH payload, not additional rounds */
749 return NEED_MORE;
750 }
751 default:
752 break;
753 }
754
755 process_payloads(this, message);
756
757 return NEED_MORE;
758 }
759
760 /**
761 * handle CHILD_SA setup failure
762 */
763 static void handle_child_sa_failure(private_child_create_t *this,
764 message_t *message)
765 {
766 if (message->get_exchange_type(message) == IKE_AUTH &&
767 lib->settings->get_bool(lib->settings,
768 "charon.close_ike_on_child_failure", FALSE))
769 {
770 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
771 * first */
772 DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
773 charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
774 delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
775 100);
776 }
777 }
778
779 /**
780 * Implementation of task_t.build for responder
781 */
782 static status_t build_r(private_child_create_t *this, message_t *message)
783 {
784 peer_cfg_t *peer_cfg;
785 payload_t *payload;
786 enumerator_t *enumerator;
787 bool no_dh = TRUE;
788
789 switch (message->get_exchange_type(message))
790 {
791 case IKE_SA_INIT:
792 return get_nonce(message, &this->my_nonce);
793 case CREATE_CHILD_SA:
794 if (generate_nonce(&this->my_nonce) != SUCCESS)
795 {
796 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
797 chunk_empty);
798 return SUCCESS;
799 }
800 no_dh = FALSE;
801 break;
802 case IKE_AUTH:
803 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
804 { /* wait until all authentication round completed */
805 return NEED_MORE;
806 }
807 default:
808 break;
809 }
810
811 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
812 {
813 DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
814 message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
815 return SUCCESS;
816 }
817
818 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
819 if (peer_cfg && this->tsi && this->tsr)
820 {
821 host_t *me, *other;
822
823 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
824 if (me == NULL)
825 {
826 me = this->ike_sa->get_my_host(this->ike_sa);
827 }
828 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
829 if (other == NULL)
830 {
831 other = this->ike_sa->get_other_host(this->ike_sa);
832 }
833 this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
834 this->tsi, me, other);
835 }
836
837 if (this->config == NULL)
838 {
839 DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
840 this->tsr, this->tsi);
841 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
842 handle_child_sa_failure(this, message);
843 return SUCCESS;
844 }
845
846 /* check if ike_config_t included non-critical error notifies */
847 enumerator = message->create_payload_enumerator(message);
848 while (enumerator->enumerate(enumerator, &payload))
849 {
850 if (payload->get_type(payload) == NOTIFY)
851 {
852 notify_payload_t *notify = (notify_payload_t*)payload;
853
854 switch (notify->get_notify_type(notify))
855 {
856 case INTERNAL_ADDRESS_FAILURE:
857 case FAILED_CP_REQUIRED:
858 {
859 DBG1(DBG_IKE,"configuration payload negotation "
860 "failed, no CHILD_SA built");
861 enumerator->destroy(enumerator);
862 handle_child_sa_failure(this, message);
863 return SUCCESS;
864 }
865 default:
866 break;
867 }
868 }
869 }
870 enumerator->destroy(enumerator);
871
872 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
873 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
874 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
875
876 if (this->ipcomp_received != IPCOMP_NONE)
877 {
878 if (this->config->use_ipcomp(this->config))
879 {
880 add_ipcomp_notify(this, message, this->ipcomp_received);
881 }
882 else
883 {
884 DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
885 notify_type_names, IPCOMP_SUPPORTED);
886 }
887 }
888
889 switch (select_and_install(this, no_dh))
890 {
891 case SUCCESS:
892 break;
893 case NOT_FOUND:
894 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
895 handle_child_sa_failure(this, message);
896 return SUCCESS;
897 case INVALID_ARG:
898 {
899 u_int16_t group = htons(this->dh_group);
900 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
901 chunk_from_thing(group));
902 handle_child_sa_failure(this, message);
903 return SUCCESS;
904 }
905 case FAILED:
906 default:
907 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
908 handle_child_sa_failure(this, message);
909 return SUCCESS;
910 }
911
912 build_payloads(this, message);
913
914 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
915 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
916 this->child_sa->get_name(this->child_sa),
917 this->child_sa->get_reqid(this->child_sa),
918 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
919 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
920 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
921 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
922
923 return SUCCESS;
924 }
925
926 /**
927 * Implementation of task_t.process for initiator
928 */
929 static status_t process_i(private_child_create_t *this, message_t *message)
930 {
931 enumerator_t *enumerator;
932 payload_t *payload;
933 bool no_dh = TRUE;
934
935 switch (message->get_exchange_type(message))
936 {
937 case IKE_SA_INIT:
938 return get_nonce(message, &this->other_nonce);
939 case CREATE_CHILD_SA:
940 get_nonce(message, &this->other_nonce);
941 no_dh = FALSE;
942 break;
943 case IKE_AUTH:
944 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
945 { /* wait until all authentication round completed */
946 return NEED_MORE;
947 }
948 default:
949 break;
950 }
951
952 /* check for erronous notifies */
953 enumerator = message->create_payload_enumerator(message);
954 while (enumerator->enumerate(enumerator, &payload))
955 {
956 if (payload->get_type(payload) == NOTIFY)
957 {
958 notify_payload_t *notify = (notify_payload_t*)payload;
959 notify_type_t type = notify->get_notify_type(notify);
960
961 switch (type)
962 {
963 /* handle notify errors related to CHILD_SA only */
964 case NO_PROPOSAL_CHOSEN:
965 case SINGLE_PAIR_REQUIRED:
966 case NO_ADDITIONAL_SAS:
967 case INTERNAL_ADDRESS_FAILURE:
968 case FAILED_CP_REQUIRED:
969 case TS_UNACCEPTABLE:
970 case INVALID_SELECTORS:
971 {
972 DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
973 notify_type_names, type);
974 enumerator->destroy(enumerator);
975 handle_child_sa_failure(this, message);
976 /* an error in CHILD_SA creation is not critical */
977 return SUCCESS;
978 }
979 case INVALID_KE_PAYLOAD:
980 {
981 chunk_t data;
982 diffie_hellman_group_t bad_group;
983
984 bad_group = this->dh_group;
985 data = notify->get_notification_data(notify);
986 this->dh_group = ntohs(*((u_int16_t*)data.ptr));
987 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
988 "it requested %N", diffie_hellman_group_names,
989 bad_group, diffie_hellman_group_names, this->dh_group);
990
991 this->public.task.migrate(&this->public.task, this->ike_sa);
992 enumerator->destroy(enumerator);
993 return NEED_MORE;
994 }
995 default:
996 break;
997 }
998 }
999 }
1000 enumerator->destroy(enumerator);
1001
1002 process_payloads(this, message);
1003
1004 if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
1005 {
1006 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
1007 " one, no CHILD_SA built");
1008 handle_child_sa_failure(this, message);
1009 return SUCCESS;
1010 }
1011 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
1012 {
1013 DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
1014 "IPComp is disabled");
1015 this->ipcomp = IPCOMP_NONE;
1016 }
1017 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
1018 {
1019 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1020 "no CHILD_SA built");
1021 handle_child_sa_failure(this, message);
1022 return SUCCESS;
1023 }
1024
1025 if (select_and_install(this, no_dh) == SUCCESS)
1026 {
1027 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
1028 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1029 this->child_sa->get_name(this->child_sa),
1030 this->child_sa->get_reqid(this->child_sa),
1031 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
1032 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
1033 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
1034 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
1035 }
1036 else
1037 {
1038 handle_child_sa_failure(this, message);
1039 }
1040 return SUCCESS;
1041 }
1042
1043 /**
1044 * Implementation of task_t.get_type
1045 */
1046 static task_type_t get_type(private_child_create_t *this)
1047 {
1048 return CHILD_CREATE;
1049 }
1050
1051 /**
1052 * Implementation of child_create_t.use_reqid
1053 */
1054 static void use_reqid(private_child_create_t *this, u_int32_t reqid)
1055 {
1056 this->reqid = reqid;
1057 }
1058
1059 /**
1060 * Implementation of child_create_t.get_child
1061 */
1062 static child_sa_t* get_child(private_child_create_t *this)
1063 {
1064 return this->child_sa;
1065 }
1066
1067 /**
1068 * Implementation of child_create_t.get_lower_nonce
1069 */
1070 static chunk_t get_lower_nonce(private_child_create_t *this)
1071 {
1072 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1073 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1074 {
1075 return this->my_nonce;
1076 }
1077 else
1078 {
1079 return this->other_nonce;
1080 }
1081 }
1082
1083 /**
1084 * Implementation of task_t.migrate
1085 */
1086 static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
1087 {
1088 chunk_free(&this->my_nonce);
1089 chunk_free(&this->other_nonce);
1090 if (this->tsi)
1091 {
1092 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1093 }
1094 if (this->tsr)
1095 {
1096 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1097 }
1098 DESTROY_IF(this->child_sa);
1099 DESTROY_IF(this->proposal);
1100 DESTROY_IF(this->dh);
1101 if (this->proposals)
1102 {
1103 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1104 }
1105
1106 this->ike_sa = ike_sa;
1107 this->keymat = ike_sa->get_keymat(ike_sa);
1108 this->proposal = NULL;
1109 this->proposals = NULL;
1110 this->tsi = NULL;
1111 this->tsr = NULL;
1112 this->dh = NULL;
1113 this->child_sa = NULL;
1114 this->mode = MODE_TUNNEL;
1115 this->ipcomp = IPCOMP_NONE;
1116 this->ipcomp_received = IPCOMP_NONE;
1117 this->other_cpi = 0;
1118 this->reqid = 0;
1119 this->established = FALSE;
1120 }
1121
1122 /**
1123 * Implementation of task_t.destroy
1124 */
1125 static void destroy(private_child_create_t *this)
1126 {
1127 chunk_free(&this->my_nonce);
1128 chunk_free(&this->other_nonce);
1129 if (this->tsr)
1130 {
1131 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1132 }
1133 if (this->tsi)
1134 {
1135 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1136 }
1137 if (!this->established)
1138 {
1139 DESTROY_IF(this->child_sa);
1140 }
1141 DESTROY_IF(this->proposal);
1142 DESTROY_IF(this->dh);
1143 if (this->proposals)
1144 {
1145 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1146 }
1147
1148 DESTROY_IF(this->config);
1149 free(this);
1150 }
1151
1152 /*
1153 * Described in header.
1154 */
1155 child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
1156 {
1157 private_child_create_t *this = malloc_thing(private_child_create_t);
1158
1159 this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child;
1160 this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce;
1161 this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid;
1162 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
1163 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
1164 this->public.task.destroy = (void(*)(task_t*))destroy;
1165 if (config)
1166 {
1167 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
1168 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
1169 this->initiator = TRUE;
1170 config->get_ref(config);
1171 }
1172 else
1173 {
1174 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
1175 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
1176 this->initiator = FALSE;
1177 }
1178
1179 this->ike_sa = ike_sa;
1180 this->config = config;
1181 this->my_nonce = chunk_empty;
1182 this->other_nonce = chunk_empty;
1183 this->proposals = NULL;
1184 this->proposal = NULL;
1185 this->tsi = NULL;
1186 this->tsr = NULL;
1187 this->dh = NULL;
1188 this->dh_group = MODP_NONE;
1189 this->keymat = ike_sa->get_keymat(ike_sa);
1190 this->child_sa = NULL;
1191 this->mode = MODE_TUNNEL;
1192 this->ipcomp = IPCOMP_NONE;
1193 this->ipcomp_received = IPCOMP_NONE;
1194 this->my_spi = 0;
1195 this->other_spi = 0;
1196 this->my_cpi = 0;
1197 this->other_cpi = 0;
1198 this->reqid = 0;
1199 this->established = FALSE;
1200
1201 return &this->public;
1202 }