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