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